是否可以为以下(或类似)命令显示任何类型的进度指示器?
$dir = 'C:\$Recycle.Bin\S-1-5-18\'
(Get-ChildItem -LiteralPath $dir -File -Recurse -Force -ErrorAction SilentlyContinue | Measure-Object -Property Length -Sum).Sum / 1GB
(将其输出通过管道传输到“
Powershell Get-ChildItem进度问题”的其中一个答案中建议的
%{Write-Output processing item: $_.fullname; $_}
之类的东西 - 似乎不起作用。例如,
$dir = 'C:\$Recycle.Bin\S-1-5-18\'
(Get-ChildItem -LiteralPath $dir -File -Force -ErrorAction SilentlyContinue | %{Write-Output processing item: $_.fullname; $_} | Measure-Object -Property Length -Sum).Sum / 1GB
...除了最终结果(大小以 GB 为单位)之外,根本不产生任何输出。
在我们的许多服务器上,
C:\$Recycle.Bin\S-1-5-18\
(“系统”帐户的回收站目录)包含数百万个文件,数百或数千个子目录(也可能包含大量文件),并且不断被填满速率为 1-3GB/天。
罪魁祸首是这些服务器上行为不当的“业务线”应用程序,它似乎将大量临时文件写入回收站。目前,不是可以选择阻止它或改变其行为。
我的首要任务是:
NukeOnDelete
、NeedToPurge
和 MaxCapacity
)或强制永久删除文件的 GPO 设置注册表值。第一部分,使用 Powershell 从回收站清除文件,似乎需要首先通过
Get-ChildItem
获取要删除的项目列表 - 这对于驻留在相当慢的磁盘上的大型目录来说需要很长很长时间。
有没有办法在通过管道传输到
Get-ChildItem
或类似命令时获取 Measure-Object
正在执行某些操作的指示符(例如,到目前为止它能够收集的项目数量)?
附注我认为这可能是可能的原因是因为
Get-ChildItem
本身(没有到 Measure-Object
的管道)立即开始输出。像 TreeSize 这样的实用程序似乎能够在“遍历”目录树和收集数据时显示进度。 dir /a/s C:\$Recycle.Bin\S-1-5-18\
也会立即开始输出,即使需要很长时间才能完成。当我们通过管道将其传输到 Measure-Object
或类似命令时,是否有机会获得进度指示器?
DirectoryInfo
中的 .NET API 和 Queue<T>
来遍历初始目录。这样做的好处是性能,并且您将能够在遍历目录时跟踪总长度。
$queue = [System.Collections.Generic.Queue[System.IO.DirectoryInfo]]::new()
$initialItem = Get-Item 'C:\$Recycle.Bin\S-1-5-18\' -ErrorAction Stop
$queue.Enqueue($initialItem)
$totalLength = 0
while ($queue.Count) {
$current = $queue.Dequeue()
$writeProgressSplat = @{
Activity = 'Total Length: {0, 10} Gb' -f [Math]::Round($totalLength / 1gb, 2)
Status = "Processing: '{0}'" -f $current.FullName
}
Write-Progress @writeProgressSplat
try {
$enum = $current.EnumerateFileSystemInfos()
}
catch {
# we can't enumerate this dir, add error handling here
# or empty to ignore enumeration errors
# dont remove this!
continue
}
foreach ($item in $enum) {
if ($item -is [System.IO.DirectoryInfo]) {
$queue.Enqueue($item)
continue
}
$totalLength += $item.Length
}
}