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

用于删除不在进度条列表中的文件的Powershell脚本,powershell,progress-bar,delete-file,Powershell,Progress Bar,Delete File,我有一个文件夹,里面有.jpg文件。我将这些与access数据库中的产品相关联。产品的一个来源提供了这些.jpg文件,但它们不允许您仅轻松下载当前使用的图片。因此,我找到了一个PowerShell脚本来删除我不需要的文件 $exclusions = Get-Content C:\Users\office\Desktop\ExcludedPhotos.txt dir -rec M:\PhotoDirectory\PhotoFolder | Where-Object {$exclusions -no

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

$exclusions = Get-Content C:\Users\office\Desktop\ExcludedPhotos.txt
dir -rec M:\PhotoDirectory\PhotoFolder | Where-Object {$exclusions -notcontains $_.name } | Remove-Item
归功于@x0n

而且效果很好!但问题是这需要永远的时间,我有超过180000个项目需要搜索和删除。所以我想制作一个进度条,让我知道我在这个过程中走了多远

因此,经过一点搜索,我找到了一篇名为“使用进度条”的文章

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

$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
        }
然而,这似乎比原始脚本要花更长的时间,我不知道它是如何工作的,我正在测试它,而我只需要删除10-15个文件

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

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

然而,这似乎比最初的剧本花费的时间更长


这是因为您尝试枚举、筛选和删除文件100次,这显然是不必要的

您要做的是计算删除文件的过程中的距离,然后将其作为传递给
写入进度
的百分比的基础。保持计数的最简单方法可能是使用常规的
for
循环:

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


另一个用来表示百分比的特征是删除的相对卷(总字节数)。我们只需跟踪需要删除的总字节数,以及到目前为止已删除的字节数,就可以做到这一点:

$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

正如@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

您希望执行类似的操作(请注意,这是未经测试的,因此我已将
-whatif
放在remove cmdlet上,当您满意它正常工作时,应该将其删除):


如果要删除的文件数非常高,他还将受益于不使用每个文件而是每隔几个文件写入进度。例如,将计数除以100,四舍五入到最接近的整数,然后将其用作计数器的模数。例如,对于1-100个文件,您将写入每个文件的进度。200,每隔一个文件。对于1000,每10个…另外,我看到一个非常大的树上的递归get项非常慢。我在获取item-recurse-directory,然后迭代获取item-file方面运气更好。我在这方面写了一些变体,用于验证OS VHD或WIM内容。“这是因为您尝试枚举、筛选和删除文件100次,这显然是不必要的。”这是有道理的,当然,这将需要更长的时间,因为我正试图让它在整个脚本中运行100次,并给自己一个进度条,告诉我什么时候完成重复自己。我喜欢这个选项,它计算删除的总字节数。“我要试试看,然后带着我的发现回来。”马修维特莫尔说得很好,他用第一个例子计算了1%increments@MatthewWetmore同样有效,但执行循环体180000次,而不是100次:-)
[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
$exclusions = Get-Content C:\Users\office\Desktop\ExcludedPhotos.txt 
$files = dir -rec M:\PhotoDirectory\PhotoFolder | Where-Object {$exclusions -notcontains $_.name } 

$files | foreach-object {
    $num += 1    
    Write-Progress -Activity "Deleting Files" -Status "$_ %" -Id 1 -PercentComplete (($num / $files.count) * 100)  -CurrentOperation "Deleting File $($_.name)"
    $_ | Remove-Item -WhatIf
}