我可以更快地制作这个脚本吗?

Deu*_*ity 2 windows powershell powershell-4.0

我为实习编写了一个简单的脚本,它通过提供的目录进行拖拽并删除任何超过指定天数的文件.我今天花了我所有的空闲时间试图收紧它.这是我到目前为止所得到的:

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
}
Run Code Online (Sandbox Code Playgroud)

以下是函数调用的示例:

delOld -dir "C:\Users\me\Desktop\psproject" -numDays 5
Run Code Online (Sandbox Code Playgroud)

对于阅读的难度感到抱歉,我发现将操作压缩到一行比在每次迭代中将它们重新分配给清晰变量更有效.出于测试目的,此时删除项目已被删除.我知道在这一点上,我可能无法加快速度,但是,我在TB文件上运行它,所以每个操作都很重要.

提前感谢您提供的任何建议!

mkl*_*nt0 5

保持PowerShell和.NET方法的领域,以下是如何加速您的功能:

  • 预先计算一次截止时间戳.

  • [IO.DirectoryInfo]类型的EnumerateFiles()方法(PSv3 +/.NET4 +)与foreach 语句结合使用.wOxxOm帽子的提示.

    • EnumerateFiles()一次枚举一个文件,保持内存使用不变,类似但更快Get-ChildItem.

      • 警告:

        • EnumerateFiles() 总是包含隐藏文件,而Get-ChildItem默认情况下排除它们,并且只有-Force在指定时才包含它们.

        • EnumerateFiles()如果由于缺少权限而有可能遇到不可访问的目录是不合适的,因为即使您将整个 foreach语句包含在try/ catchblock中,只有在遇到第一个不可访问的目录时迭代停止时,您才会获得部分输出.

        • 枚举顺序可以不同于Get-ChildItem.

    • PowerShell的foreach 语句ForEach-Object cmdlet快得多,并且比PSv4 + .ForEach()收集方法更快.

  • .Delete()直接在[System.IO.FileInfo]循环体内的每个实例上调用该方法.

注意:为简便起见,下面的函数中没有错误检查,例如是否$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 }
    }
}
Run Code Online (Sandbox Code Playgroud)

注意:上面只输出要删除的文件的路径; 更换$file.FullName$file.Delete()执行实际删除.