文件夹删除脚本中的非终止异常

时间:2012-12-07 10:15:49

标签: powershell powershell-v2.0

我写了一个Powershell脚本,会定期删除我机器上的文件夹。 算法如下:

  • 深入查看每个目录结构中的最低子文件夹
  • 检查子文件夹的创建日期
  • 如果是14天或更早,请将其删除
  • 记录所有事情(不是算法的一部分,只是好的做法)

运行时,它完全按预期运行......

...除了它抛出以下非终止异常:

Get-ChildItem : Could not find a part of the path 'C:\foo\baz'.
At C:\src\CoreDev\Trunk\Tools\BuildClean script\buildclean.ps1:55 char:15
+     Get-ChildItem <<<<  -recurse -force |
    + CategoryInfo          : ReadError: (C:\foo\baz:String) [Get-ChildItem],
   DirectoryNotFoundException
    + FullyQualifiedErrorId : DirIOError,Microsoft.PowerShell.Commands.GetChil
   dItemCommand

为什么会这样?更重要的是,如何删除它,是否会导致问题?

脚本如下:

# folderclean.ps1

# This script will remove each leaf node of a directory, provided that leaf is over
# 14 days old.

# CONSTANT DECLARATIONS
# testing (run on my local machine)
$proj_loc = "C:\foo", "C:\bar"
$logpath = "C:\Logs\BuildClean\$(Get-Date -format yyyyMMdd).log"

function Write-ToLogFile {
    param ([string]$stringToWrite)

    Add-Content $logpath -value $stringToWrite
}

# Function to check if a folder is a leaf folder.
#   First, retrieve the directory $item is pointing to
#   Then, create a list of children of $item that are folders
#   If this list is either empty or null, return $true
#   Otherwise, return $false
function Folder-IsLeaf($item) {
    $ary = Get-ChildItem $item -force | ?{ $_.PSIsContainer }
    if (($ary.length) -eq 0 -or $ary -eq $null) {
        return $true
    }

    return $false
}

# Deletes leaf folders that are older than a certain threshhold.
#   Get a list of children of the folder, where each child is a folder itself and 
#       was created over 14 days ago and the folder is a leaf
#   For each of these children, delete them and increment $folderCount
#   Get a list of children of the folder, where each child is a folder itself and 
#       was last modified over 14 days ago and the folder is a leaf
#   For each of these children, delete them and increment $folderCount
function Remove-LeafFolders($path) {
    $createdCount = 0
    $modifiedCount = 0

    Write-ToLogFile "Operation started at $(Get-Date -format "dd/MM/yyyy hh:mm:ss.fff")"
    Write-ToLogFile "Looking in $proj_loc"
    Write-ToLogFile ""
    $start = $(Get-Date)

    $proj_loc | 
    Get-ChildItem -recurse -force | 
    ?{
        $_.PSIsContainer -and ($_.CreationTime).AddDays(15) -lt $(Get-Date) -and $(Folder-IsLeaf $_.FullName) -eq $true
    } | %{
        $formattedDate = $($_.CreationTime).ToString("dd/MM/yyyy hh:mm:ss");
        Write-ToLogFile "Folder $($_.FullName) is being removed; created: $formattedDate"
        Remove-Item $_.FullName -recurse;
        $createdCount += 1
    }

    $end = $(Get-Date)
    $elapsed = $end - $start
    Write-ToLogFile "Operation completed at $(Get-Date -format "dd/MM/yyyy hh:mm:ss.fff")."
    Write-ToLogFile "Folders removed: $createdCount"
    Write-ToLogFile "Time elapsed: $(($elapsed).TotalMilliseconds) ms"
    Write-ToLogFile "-------------------------------"
}

Remove-LeafFolders($proj_loc)

2 个答案:

答案 0 :(得分:0)

我找到了this other StackOverflow question,在查看答案后,我意识到问题就在于管道。所以,我改变了我的代码如下:

...
$leafList = $proj_loc | 
    Get-ChildItem -recurse -force | 
    ?{

        $_.PSIsContainer -and ($_.CreationTime).AddDays(15) -lt $(Get-Date) -and $(Folder-IsLeaf $_.FullName) -eq $true
    }

    Foreach ($folder in $leafList)
    {
        $formattedDate = $($folder.CreationTime).ToString("dd/MM/yyyy hh:mm:ss");
        Write-ToLogFile "Folder $($folder.FullName) is being removed; created: $formattedDate"
        Remove-Item $folder.FullName -recurse;
        $createdCount += 1
    }
...

我创建了一些本地文件夹,并用它们搞砸了。没有例外,因此这似乎有效:

Operation started at 10/12/2012 05:16:18.631
Looking in C:\foo C:\bar

Folder C:\foo\baz is being removed; created: 09/01/2010 02:00:00
Folder C:\bar\baz3\recursion is being removed; created: 01/01/2008 01:00:00
Operation completed at 10/12/2012 05:16:18.748.
Folders removed: 2
Time elapsed: 33.0033 ms
-------------------------------
Operation started at 10/12/2012 05:41:59.246
Looking in C:\foo C:\bar

Folder C:\foo\baz2\NewFolder is being removed; created: 10/10/2010 10:10:10
Folder C:\bar\baz3\barbar is being removed; created: 20/11/2012 05:37:38
Operation completed at 10/12/2012 05:41:59.279.
Folders removed: 2
Time elapsed: 21.0021 ms
-------------------------------

答案 1 :(得分:-1)

我认为使用自下而上的方法而不是自上而下的方式完成这种递归删除会更容易,这是Get-ChildItem默认提供的。试试这个:

$proj_loc | 
    Get-ChildItem -recurse -force -Name | sort -desc | Get-Item |
    ? { ....
    }