删除早于 xx 天的文件
Delete files older than xx days
我需要以编程方式(最好使用 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
}
与其遍历所有文件并将标记为删除的文件存储在列表中,然后再次遍历列表中的每个文件,不如在找到它们时将每个文件通过管道传输到下一个命令。
所以替换这个:
$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
要满足您批量删除 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。
我不得不承认我对 robocopy 的工作方式有点误解。虽然它可以删除文件,但当被告知时,它仍然必须执行复制操作。所以这个建议最好在目标机器上 运行 而不是使用 UNC 路径。除了失望之外,我仍然认为这是一个可行的解决方案。这里最主要的是 robocopy 将 select 仅我们需要的文件而不进行任何 post 处理。
$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
放在那里。
我需要以编程方式(最好使用 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
}
与其遍历所有文件并将标记为删除的文件存储在列表中,然后再次遍历列表中的每个文件,不如在找到它们时将每个文件通过管道传输到下一个命令。
所以替换这个:
$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
要满足您批量删除 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。
我不得不承认我对 robocopy 的工作方式有点误解。虽然它可以删除文件,但当被告知时,它仍然必须执行复制操作。所以这个建议最好在目标机器上 运行 而不是使用 UNC 路径。除了失望之外,我仍然认为这是一个可行的解决方案。这里最主要的是 robocopy 将 select 仅我们需要的文件而不进行任何 post 处理。
$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
放在那里。