我跑:
PS F:\> gci F:\logs\PRV_RequestLogs\inbound -r -directory | %{ $_.fullname }
它显示:
F:\logs\PRV_RequestLogs\inbound\2020-02-03
F:\logs\PRV_RequestLogs\inbound\2020-02-04
...
F:\logs\PRV_RequestLogs\inbound\2022-05-09
F:\logs\PRV_RequestLogs\inbound\2022-05-10
然后它“挂”在那里。
然后我在另一个窗口中运行以下命令,试图找出发生了什么:
PS F:\> C:\temp\handle64.exe -p 3204
我发现:
ACC: File (RWD) F:\logs\PRV_RequestLogs\inbound\2020-04-28
...
F08: File (RWD) F:\logs\PRV_RequestLogs\inbound\2020-04-28
而且目录不断变化,所以它遍历每个目录寻找子目录,里面没有但有很多文件。
完成该过程需要几个小时。没想到这个过程会这么慢。看起来它会遍历每个文件并测试它是否是一个目录。有没有更快的方法来做到这一点?我在 Windows 2012R2 上使用 powershell 5.0。
最佳答案
Get-ChildItem
众所周知,递归遍历目录的速度很慢,但它是 PowerShell 内置的,它是一个非常方便且易于使用的 cmdlet。如果您追求速度和效率,您可能需要默认使用 .NET API 调用 IO.Directory
.
还没有对此进行足够的测试,但我相信它应该可以工作,例如,在本例中找到任何空的且超过 90 天的目录。
值得注意的是,如果运行 Windows PowerShell,此代码需要 .NET Framework 4+。
$queue = [Collections.Generic.Queue[IO.DirectoryInfo]]::new()
$olderThan = [datetime]::Now.AddDays(-90) # => Set limit date here!
$queue.Enqueue('F:\logs\PRV_RequestLogs\inbound') # => Starting path here!
while($queue.Count) {
$dir = $queue.Dequeue()
try {
$isEmpty = $true
foreach ($i in $dir.EnumerateDirectories()) {
if($i.Attributes -band [IO.FileAttributes]::ReparsePoint) {
# skip if it is ReparsePoint
continue
}
$isEmpty = $false
$queue.Enqueue($i)
}
if($isEmpty -and $dir.CreationTime -lt $olderThan -and -not $dir.EnumerateFiles().GetEnumerator().MoveNext()) {
# output the directory if the 3 conditions are `$true`, no folders or files and older than
$dir
}
}
catch {
# if we were unable to enumerate this directory, go next
continue
}
}
相关文档
关于当有大量文件时,Powershell 在 "get-childitem . -directory -recurse"中运行缓慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72193074/