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)
4

2 に答える 2

0

この他の 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
-------------------------------
于 2012-12-10T17:43:32.550 に答える
-1

Get-ChildItem がデフォルトで提供するトップダウンではなく、ボトムアップのアプローチを使用して、この種の再帰的な削除を実現する方が簡単だと思います。代わりにこれを試してください:

$proj_loc | 
    Get-ChildItem -recurse -force -Name | sort -desc | Get-Item |
    ? { ....
    }
于 2012-12-10T17:12:06.700 に答える