且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

我可以让这个脚本更快吗?

更新时间:2023-12-05 14:17:58

停留在 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 than Get-ChildItem.

  • 注意事项:

  • EnumerateFiles() 总是包括隐藏文件,而Get-ChildItem默认排除它们, 并且仅在指定了 -Force 时才包括它们.

  • EnumerateFiles() invariably includes hidden files, whereas Get-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 statementForEach-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.