我需要从一个文件夹中以编程方式删除一些文件(最好使用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
}
答案 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
放在那里。