用于删除不在带有进度条的列表中的文件的 Powershell 脚本

Lib*_*r17 3 powershell delete-file progress-bar

我有一个包含 .jpg 文件的文件夹。我将这些与访问数据库中的产品相关联。产品来源之一提供了这些 .jpg 文件,但它们不允许您仅轻松下载当前使用的图片。因此,我找到了一个 PowerShell 脚本来删除我不需要的文件。

$exclusions = Get-Content C:\Users\office\Desktop\ExcludedPhotos.txt
dir -rec M:\PhotoDirectory\PhotoFolder | Where-Object {$exclusions -notcontains $_.name } | Remove-Item
Run Code Online (Sandbox Code Playgroud)

归功于@x0n Powershell 脚本,用于删除列表中未指定的文件

而且效果很好!但问题是它需要永远,我有超过 180,000 项要搜索和删除。所以我想做一个进度条,让我知道我已经完成了多少过程。

所以经过一番搜索,我找到了一篇名为“使用进度条”的文章

问题是我不知道如何将两者混合在一起,但是我在这里尝试过:

$exclusions = Get-Content C:\Users\office\Desktop\ExcludedPhotos.txt 
  1..100 | foreach-object {
    Write-Progress -Activity "Deleting Files" -Status "$_ %" -Id 1 -PercentComplete $_ -CurrentOperation "Deleting File $_"
       dir -rec M:\PhotoDirectory\PhotoFolder | Where-Object {$exclusions -notcontains $_.name } | Remove-Item
        }
Run Code Online (Sandbox Code Playgroud)

然而,这似乎比原始脚本花费的时间更长,我不知道它是如何工作的,当我只需要删除 10-15 个文件时,我正在测试它。

很可能我缺少一些非常基本的东西,但我真的很感激能帮助理解这一点。

在这里,我添加了一个屏幕截图:

PowerShell 控制台

Mat*_*sen 5

然而,这似乎比原始脚本花费的时间更长

那是因为您试图枚举、过滤和删除文件 100 次——这显然是不必要的。

您想要做的是计算您在删除文件的过程中走了多远,然后将其用作传递给Write-Progress. 保持计数的最简单方法可能是使用常规for循环:

注意:前两个示例非常通用,请转到底部的示例,其中考虑了您的卷(~180.000 个文件)。

# Grab all the files you need to delete
$exclusions = Get-Content C:\Users\office\Desktop\ExcludedPhotos.txt
$filesToDelete = Get-ChildItem M:\PhotoDirectory\PhotoFolder -Recurse | Where-Object {$exclusions -notcontains $_.Name }

for($i = 0; $i -lt $filesToDelete.Count; $i++){
    # calculate progress percentage
    $percentage = ($i + 1) / $filesToDelete.Count * 100
    Write-Progress -Activity "Deleting Files" -Status "Deleting File #$($i+1)/$($filesToDelete.Count)" -PercentComplete $percentage
    # delete file
    $filesToDelete[$i] |Remove-Item
}
# All done
Write-Progress -Activity "Deleting Files" -Completed
Run Code Online (Sandbox Code Playgroud)

您可能想要用来表示百分比的另一个特征是移除的相对量(总字节数)。我们可以通过简单地跟踪我们需要删除的字节总数以及到目前为止我们已经删除的字节数来做到这一点:

$exclusions = Get-Content C:\Users\office\Desktop\ExcludedPhotos.txt
$filesToDelete = Get-ChildItem M:\PhotoDirectory\PhotoFolder -Recurse | Where-Object {$exclusions -notcontains $_.Name }
$TotalSize = ($filesToDelete |Measure-Object -Property Length -Sum).Sum
$BytesRemoved = 0

foreach($file in $filesToDelete){
    $percentage = $BytesRemoved / $TotalSize * 100
    Write-Progress -Activity "Deleting Files" -Status "Deleted $BytesRemoved/$TotalSize bytes" -PercentComplete $percentage
    $file |Remove-Item
    $BytesRemoved += $file.Length
}
Write-Progress -Activity "Deleting Files" -Completed
Run Code Online (Sandbox Code Playgroud)

正如@MatthewWetmore 指出的那样,Write-Progress每次删除文件时调用当然会产生一些开销。对于 180.000 个文件,当进度从 3.56325% 到 3.56331% 时,您可能对 UI 更新不那么感兴趣

您可以做的是使用for循环以整个项目集的 1% 为增量进行计数,然后在每次迭代时删除整个范围的文件:

[int]$hundredthStep = $filesToDelete.Count / 100
for($i = 0; $i -lt $filesToDelete.Count; $i += $hundredthStep){
    # calculate progress percentage
    $percentage = ($i + 1) / $filesToDelete.Count * 100
    Write-Progress -Activity "Deleting Files" -Status "Deleting File up to #$($i+1)/$($filesToDelete.Count)" -PercentComplete $percentage
    # delete file
    $filesToDelete[$i..($i + $hundredthStep - 1)] |Remove-Item
}
# All done
Write-Progress -Activity "Deleting Files" -Completed
Run Code Online (Sandbox Code Playgroud)