删除早于xx天的文件

时间:2016-06-28 19:42:28

标签: powershell filesystems delete-file

我需要从一个文件夹中以编程方式删除一些文件(最好使用Powershell),而不是超过给定天数。

我已经编写了一个简单的脚本来执行此操作,但是我遇到的问题是,由于文件夹中的文件数量庞大,它似乎很难开始删除。

我正在寻找批量删除的方法。所以它可能会得到第一个1000,删除,然后等等。

现在,该文件夹可能有几十万个文件,几乎不可能遍历。

Param(
  [Parameter(Mandatory=$true)][string]$Path,
  [Parameter(Mandatory=$true)][string]$DaysToDelete
)

$limit = (Get-Date).AddDays($DaysToDelete)
$LogFile = "FileCleanupLog-$(Get-Date -f yyyyMMdd_HH_mm_ss).txt";

function Log-Message
{
   Param ([string]$logtext)
   Add-content $LogFile -value $logtext
}

If (-Not (Test-Path $Path))
{
    Write-Host "Invalid Path provided!" -ForegroundColor Red
    Exit
}

$files = Get-ChildItem -Path $Path -Recurse -Force | Where-Object { !$_.PSIsContainer -and $_.CreationTime -lt $limit }

If ($files.Count -GT 1) {
    $files | % {$directory=$_.DirectoryName;(Log-Message "Deleting File $directory\$_");$_ } | Remove-Item -Force 
}

3 个答案:

答案 0 :(得分:2)

不是循环遍历所有文件并将标记为删除的文件存储在列表中,然后再循环遍历列表中的每个文件,只需将每个文件传送到下一个命令即可。

所以替换这个:

$files = Get-ChildItem -Path $Path -Recurse -Force | Where-Object { !$_.PSIsContainer -and $_.CreationTime -lt $limit }

If ($files.Count -GT 1) {
    $files | % {$directory=$_.DirectoryName;(Log-Message "Deleting File $directory\$_");$_ } | Remove-Item -Force 
}

有这样的事情:

Get-ChildItem -Path $Path -Recurse -Force `
| Where-Object { !$_.PSIsContainer -and $_.CreationTime -lt $limit } `
| % {
    $directory=$_.DirectoryName
    (Log-Message "Deleting File $directory\$_")
    $_ } `
| Remove-Item -Force

答案 1 :(得分:1)

要满足批量删除1000个文件的条件,请使用以下命令。 select -first 1000将使其每次通过while循环时仅删除1000个文件。

while($true){
    $files = Get-ChildItem -Path $Path -Recurse -Force | Where-Object { !$_.PSIsContainer -and $_.CreationTime -lt $limit } | select -first 1000
    If ($files.Count -GT 1) {
        $files | % {$directory=$_.DirectoryName;(Log-Message "Deleting File $directory\$_");$_ } | Remove-Item -Force 
    } else {
        exit 
    }
}

我不知道这是否会更快 - 这取决于PowerShell是否足够聪明,可以在找到前1000个文件后停止get-childitem。

答案 2 :(得分:1)

我必须承认,我有点误以为我希望robocopy能够工作。虽然它可以删除文件,但当被告知时,它仍然必须执行复制操作。所以这个建议最好在目标机器上运行,而不是使用UNC路径。除了令人失望之外,我仍然认为这是一个可行的解决方案。这里的主要内容是robocopy将只选择我们需要的文件而无需任何后期处理。

$sourceDirectory = "D:\temp\New folder"
$dummyDirectory = "D:\temp\trashbin"
$loggingFile = "D:\temp\FileCleanupLog-$(Get-Date -f yyyyMMdd_HH_mm_ss).txt"

# Build the dummy directory. It will be deleted in the end.
New-Item -Path $dummyDirectory -ItemType Directory | Out-Null

& robocopy.exe $sourceDirectory /njh /ndl /nc /njs /minage:$days /mov /e /ns /np /l | Set-Content $loggingFile

# Purge the dummy directory with all the content we don't want
Remove-Item -Path $dummyDirectory -Force -Confirm:$false -Recurse

以下是所有使用的开关代表的内容。大多数是清理输出以进行日志记录。日志应该只有一个已删除的完整路径列表。这目前不会影响目录结构。如果需要,交换机更改将解决此问题。您还将看到/l仅用于记录。您可以使用该开关进行测试,以查看是否要删除所需的文件。对于实际的生产测试,您需要删除它。

/minage:N        Specifies the minimum file age (exclude files newer than N days or date).
/njh             Specifies that there is no job header.
/njs             Specifies that there is no job summary.
/l               Specifies that files are to be listed only (and not copied, deleted, or time stamped).
/mov             Moves files, and deletes them from the source after they are copied.
/ndl             Specifies that directory names are not to be logged.
/nc              Specifies that file classes are not to be logged.\
/np              Specifies that the progress of the copying operation (the number of files or directories copied so far) will not be displayed.

如果不花时间在屏幕上显示数据,这也会更快地执行。这就是为什么我特意把/np放在那里。