我可以让这个脚本更快吗? [英] Can I make this script even faster?
问题描述
我为实习编写了一个简单的脚本,它遍历提供的目录并删除任何早于指定天数的文件.我今天所有的空闲时间都在试图收紧它.这是我到目前为止所得到的:
I wrote a simple script for an internship, which trawls through a provided directory and deletes any file older than a specified number of days. I've spent all my free time today attempting to tighten it up. Here's what I've got so far:
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
}
这是一个函数调用的例子:
Here is an example of a call of the function:
delOld -dir "C:\Users\me\Desktop\psproject" -numDays 5
抱歉阅读困难,我发现将操作压缩为一行比每次迭代将它们重新分配给清晰的变量更有效.出于测试目的,删除项目目前是 whatif'd.我知道在这一点上,我可能无法加快速度,但是,我在 TB 的文件上运行它,所以每个操作都很重要.
Sorry for the difficulty of reading, I found that condensing the operations into one line was more efficient than reassigning them to legible variables each iteration. The remove-item is whatif'd at the moment for testing purposes. I'm aware that at this point, I probably cannot speed it up much, however, I am running it on over a TB of files, so every operation counts.
预先感谢您提供的任何建议!
Thanks in advance for any advice you have to offer!
推荐答案
停留在 PowerShell 和 .NET 方法领域,您可以通过以下方式加快函数速度:
Staying in the realm of PowerShell and .NET methods, here's how you can speed up your function:
预先计算截止时间戳一次.
将 [IO.DirectoryInfo]
类型的 EnumerateFiles()
方法 (PSv3+/.NET4+) 与 foreach
结合使用声明.wOxxOm.
Use the [IO.DirectoryInfo]
type's EnumerateFiles()
method (PSv3+ / .NET4+) in combination with a foreach
statement. Tip of the hat to wOxxOm.
EnumerateFiles()
一次枚举一个文件,保持内存使用不变,类似于Get-ChildItem
,但速度更快.
EnumerateFiles()
enumerates files one at a time, keeping memory use constant, similar to, but faster thanGet-ChildItem
.
注意事项:
EnumerateFiles()
总是包括隐藏文件,而Get-ChildItem
默认排除它们, 并且仅在指定了-Force
时才包括它们.
EnumerateFiles()
invariably includes hidden files, whereasGet-ChildItem
excludes them by default, and only includes them if-Force
is specified.
EnumerateFiles()
如果由于缺乏权限而有可能遇到无法访问的目录,则不适合,因为即使您将整个 foreach 括起来
语句在 try
/catch
块中,你只会得到 部分 输出,因为迭代停止 遇到第一个无法访问的目录.
EnumerateFiles()
is unsuitable if there's a chance of encountering inaccessible directories due to lack of permissions, because even if you enclose the entire foreach
statement in a try
/ catch
block, you'll only get partial output, given that the iteration stops on encountering the first inaccessible directory.
枚举顺序可以与 Get-ChildItem
的不同.
The enumeration order can differ from that of Get-ChildItem
.
PowerShell 的 foreach
statement 比 ForEach-Object
cmdlet 快得多,而且速度也更快比 PSv4+ .ForEach()
集合方法.
PowerShell's foreach
statement is much faster than the ForEach-Object
cmdlet, and also faster than the PSv4+ .ForEach()
collection method.
直接在循环体内的每个 [System.IO.FileInfo]
实例上调用 .Delete()
方法.
Invoke the .Delete()
method directly on each [System.IO.FileInfo]
instance inside the loop body.
注意:为简洁起见,下面的函数中没有错误检查,例如$numDays
是否有允许的值以及$dir
是否引用到现有目录(如果它是基于自定义 PS 驱动器的路径,则必须首先使用 Convert-Path
解析它).
Note: For brevity, there are no error checks in the function below, such as for whether $numDays
has a permissible value and whether $dir
refers to an existing directory (if it's a path based on a custom PS drive, you'd have to resolve it with Convert-Path
first).
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.FullName
替换为 $file.Delete()
以执行实际删除.
Note: The above simply outputs the paths of the files to delete; replace $file.FullName
with $file.Delete()
to perform actual deletion.
这篇关于我可以让这个脚本更快吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!