我有一个包含.jpg文件的文件夹。我将这些与访问数据库中的产品相关联。产品的一个来源提供这些.jpg文件,但它们不允许您轻松下载您当前使用的图片。因此,我找到了一个PowerShell脚本来删除我不需要的文件。
$exclusions = Get-Content C:\Users\office\Desktop\ExcludedPhotos.txt
dir -rec M:\PhotoDirectory\PhotoFolder | Where-Object {$exclusions -notcontains $_.name } | Remove-Item
归功于@ x0n Powershell script to delete files not specified in a list
它很棒!但问题是它需要永远,我有超过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
}
然而,这似乎比原始脚本花费的时间更长,我不知道它是如何工作的,我正在测试它,当我只需要删除10-15个文件时。
可能有一些我非常缺席的东西但是我真的很感激帮助理解这一点。
这里我添加了一个截图:
答案 0 :(得分:3)
However that seems to take even longer than the original script did
That's because you're attempting to enumerate, filter and delete the files 100 times - which is obviously unnecessary.
What you want to do is calculate how far in the process of deleting the files you are, and then use that as a basis for the percentage you pass to Write-Progress
. The easiest way to keep count is probably to use a regular for
loop:
Note: these first two examples are very generic, go to the bottom for an example that takes your volume (~180.000 files) into account.
# 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
Another characteristic you might want to use to indicate a percentage is the relative volume (total number of bytes) removed. We can do this by simply keeping track of how many bytes we need to remove total, and how many we've removed so far:
$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
As @MatthewWetmore points out, invoking Write-Progress
every time you delete a file will of course incur some overhead. And with 180.000 files, you're probably not that interested in having the UI update when the progress goes from 3.56325% to 3.56331%
What you could do is use the for
loop to count in increments of 1% of the entire set of items, and then remove a whole range of files on each iteration:
[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
答案 1 :(得分:1)
You want to do something like this (beware this is untested so i've put -whatif
on the remove cmdlet which you should remove when you're happy it's working correctly):
$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
}