可以吗?根据他们使用 Powershell 的时间删除大量文件
Can it be done? Delete huge amount of files based on how old they are using Powershell
在服务器 运行 上 Windows 2012 R2,版本
PS C:\Users\admin> $PSVersionTable.PSVersion
Major Minor Build Revision
----- ----- ----- --------
4 0 -1 -1
我需要删除包含很多子文件夹的文件夹中超过 180 天的文件。这很简单,BUT 当有数十万个文件并且文件夹大约 800GB 时就不行了。使用 Get-ChildItem 首先在检查日期时递归地读取所有文件,然后开始删除它们……好吧,这需要很长时间,服务器在最后 运行 内存不足。
所以 - 任何有心情帮助我加快我的代码的人,目前是这样的(删除部分)
...
...
foreach ($i in Get-ChildItem $TargetFolder -recurse -exclude
$skipFilePatterns | where { ! $i.PSIsContainer }) {
if (! $i.PSIsContainer -and $i.LastWriteTime -lt ($(Get-Date).AddDays(-$keepForDays))) {
# Add -WhatIf to test the script, remove it when confirmed
$timeStamp = $i.LastWriteTime
$fullName = $i.FullName
$log.Info("Deleting: $fullName with timestamp (LastWriteTime): $timeStamp")
Remove-Item $i.FullName -force -ErrorVariable errVar -ErrorAction SilentlyContinue
...
...
我建议一直使用管道,否则您首先会在内存中收集所有内容。在 Where-Object
过滤器中使用正则表达式可能比使用 -Exclude
更有效(这是出了名的低效)。
$limit = (Get-Date).AddDays(-180)
$skipFilePatterns = @() # probably some collection of wildcard strings
Get-ChildItem -Recurse -File -Exclude $skipFilePatterns |
Where-Object LastWriteTime -lt $limit |
ForEach-Object {
$timeStamp = $PSItem.LastWriteTime.ToString('o') # ISO-8601-compliant string
$fullName = $PSItem.FullName
$log.Info("Deleting: $fullName with timestamp (LastWriteTime): $timeStamp")
$PSItem
} | Remove-Item -Force -ErrorVariable errVar -ErrorAction SilentlyContinue
所以你可以使用Select -first $Limit
其次不需要排除文件夹 $i.PSIsContainer
你可以告诉 Get-ChildItem
(别名 GCI
)只使用 -File
参数
获取文件
类似
function Remove-ChildItemsInChunks($keepForDays, $Limit, $Path){
$count = 0
gci $Path -Recurse -File |
?{$i.LastWriteTime -lt ($(Get-Date).AddDays(-$keepForDays))} |
select -First $Limit | %{
$count += 1
Remove-Item $_
}
return $Count
}
$GCICount = Get-ChildItemsInChunks -Path C:\test -keepForDays 30 -Limit 500
while($GCICount -gt 0){
$GCICount = Get-ChildItemsInChunks -Path C:\Test -keepForDays 30 -Limit 500
}
在服务器 运行 上 Windows 2012 R2,版本
PS C:\Users\admin> $PSVersionTable.PSVersion
Major Minor Build Revision
----- ----- ----- --------
4 0 -1 -1
我需要删除包含很多子文件夹的文件夹中超过 180 天的文件。这很简单,BUT 当有数十万个文件并且文件夹大约 800GB 时就不行了。使用 Get-ChildItem 首先在检查日期时递归地读取所有文件,然后开始删除它们……好吧,这需要很长时间,服务器在最后 运行 内存不足。
所以 - 任何有心情帮助我加快我的代码的人,目前是这样的(删除部分)
...
...
foreach ($i in Get-ChildItem $TargetFolder -recurse -exclude
$skipFilePatterns | where { ! $i.PSIsContainer }) {
if (! $i.PSIsContainer -and $i.LastWriteTime -lt ($(Get-Date).AddDays(-$keepForDays))) {
# Add -WhatIf to test the script, remove it when confirmed
$timeStamp = $i.LastWriteTime
$fullName = $i.FullName
$log.Info("Deleting: $fullName with timestamp (LastWriteTime): $timeStamp")
Remove-Item $i.FullName -force -ErrorVariable errVar -ErrorAction SilentlyContinue
...
...
我建议一直使用管道,否则您首先会在内存中收集所有内容。在 Where-Object
过滤器中使用正则表达式可能比使用 -Exclude
更有效(这是出了名的低效)。
$limit = (Get-Date).AddDays(-180)
$skipFilePatterns = @() # probably some collection of wildcard strings
Get-ChildItem -Recurse -File -Exclude $skipFilePatterns |
Where-Object LastWriteTime -lt $limit |
ForEach-Object {
$timeStamp = $PSItem.LastWriteTime.ToString('o') # ISO-8601-compliant string
$fullName = $PSItem.FullName
$log.Info("Deleting: $fullName with timestamp (LastWriteTime): $timeStamp")
$PSItem
} | Remove-Item -Force -ErrorVariable errVar -ErrorAction SilentlyContinue
所以你可以使用Select -first $Limit
其次不需要排除文件夹 $i.PSIsContainer
你可以告诉 Get-ChildItem
(别名 GCI
)只使用 -File
参数
类似
function Remove-ChildItemsInChunks($keepForDays, $Limit, $Path){
$count = 0
gci $Path -Recurse -File |
?{$i.LastWriteTime -lt ($(Get-Date).AddDays(-$keepForDays))} |
select -First $Limit | %{
$count += 1
Remove-Item $_
}
return $Count
}
$GCICount = Get-ChildItemsInChunks -Path C:\test -keepForDays 30 -Limit 500
while($GCICount -gt 0){
$GCICount = Get-ChildItemsInChunks -Path C:\Test -keepForDays 30 -Limit 500
}