我为实习编写了一个简单的脚本,通过提供的目录浏览并删除任何超过指定天数的文件。 我已经花了我所有的空闲时间,试图收紧。 这是迄今为止我所得到的:
function delOld($dir, $numDays){ $timespan = new-timespan -days $numDays $curTime = get-date get-childItem $dir -Recurse -file | where-object {(($curTime)-($_.LastWriteTime)) -gt $timespan} | remove-Item -whatif }
这是一个函数调用的例子:
delOld -dir "C:\Users\me\Desktop\psproject" -numDays 5
对于阅读的难点,我发现将这些操作压缩成一行比将它们重新分配给每个迭代的易读variables更有效率。 为了testing目的,删除项目目前已被删除。 我知道,在这一点上,我可能无法加速太多,但是,我正在运行一个TB文件,所以每个操作都很重要。
预先感谢您提供的任何build议!
保持在PowerShell和.NET方法的领域,下面是如何加快你的功能:
先计算一次截断时间戳。
使用[IO.DirectoryInfo]
类型的EnumerateFiles()
方法(PSv3 + / .NET4 +)与foreach
语句结合使用。 帽子的提示wOxxOm 。
EnumerateFiles()
枚举一个文件,保持内存使用不变,类似于Get-ChildItem
,但比Get-ChildItem
快。
注意事项 :
EnumerateFiles()
总是包含隐藏的文件,而Get-ChildItem
在默认情况下将它们排除在外,只有在指定-Force
时才包含它们。 如果由于缺少权限而有可能遇到无法访问的目录,请将整个 foreach
语句放在try
/ catch
块中,以确保处理所有可访问的文件。
枚举顺序可以不同于Get-ChildItem
。
PowerShell的foreach
语句比ForEach-Object
cmdlet快得多,也比PSv4 + .ForEach .ForEach()
集合运算符更快。
直接在循环体内的每个[System.IO.FileInfo]
实例上调用.Delete()
方法。
注意:为简洁起见,在下面的函数中没有错误检查,比如$numDays
是否有一个允许的值,以及$dir
是否指向一个已经存在的目录(如果它是一个基于自定义PS驱动器的路径,先用Convert-Path
解决它)。
function delOld($dir, $numDays) { $dtCutoff = [datetime]::now - [timespan]::FromDays($numDays) # Make sure that the .NET framework's current dir. is the same as PS's: [System.IO.Directory]::SetCurrentDirectory($PWD.ProviderPath) # Enumerate all files recursively. # Replace $file.FullName with $file.Delete() to perform actual deletion. foreach ($file in ([IO.DirectoryInfo] $dir).EnumerateFiles('*', 'AllDirectories')) { if ($file.LastWriteTime -lt $dtCutOff) { $file.FullName } } }
注意:上面只是输出要删除的文件的路径; 用$file.Delete()
替换$file.FullName
来执行实际的删除操作。
许多PowerShell cmdlet比它们的.NET相当慢。 例如,您可以调用[System.IO.File]::Delete($_.FullName)
来查看是否存在性能差异。 Get-ChildItem
=> [System.IO.Directory]::GetFiles(...)
。
要做到这一点,我会写一个小脚本,创建两个临时文件夹,每个文件夹里有100,000个空的测试文件。 然后调用封装在[System.Diagnostics.StopWatch]
每个版本的函数。
一些示例代码:
$stopwatch = New-Object 'System.Diagnostics.StopWatch' $stopwatch.Start() Remove-OldItems1 ... $stopwatch.Stop() Write-Host $stopwatch.ElapsedMilliseconds $stopwatch.Reset() $stopwatch.Start() Remove-OldItems2 ... $stopwatch.Stop() Write-Host $stopwatch.ElapsedMilliseconds
PowerShell的更多布朗利点:在Powershell窗口中运行Get-Verb
,您可以看到已批准的动词列表。 建议PowerShell中的函数名为Verb-Noun
,所以像Remove-OldItems
这样的东西可以适合账单。
这将删除并行处理中的所有内容。
workflow delOld([string]$dir, [int]$numDays){ $timespan = new-timespan -days $numDays $curTime = get-date $Files = get-childItem $dir -Recurse -file | where-object {(($curTime)-($_.LastWriteTime)) -gt $timespan} foreach -parallel ($file in $files){ Remove-Item $File } } delOld -dir "C:\Users\AndrewD\Downloads" -numDays 8
现在,如果它的很多文件夹试试这个