powershell - 如何通过 UNC 加速 Powershell Get-Childitem

标签 powershell powershell-2.0

DIRGCI在 Powershell 中很慢,但在 CMD 中很快。有没有办法加快这个速度?

在 CMD.exe 中,在亚秒级延迟后,这会以 CMD 窗口可以跟上的速度响应

dir \\remote-server.domain.com\share\folder\file*.*

在 Powershell (v2) 中,经过 40 秒以上的延迟后,响应速度明显变慢(可能每秒 3-4 行)
gci \\remote-server.domain.com\share\folder\file*.*

我正在尝试扫描远程服务器上的日志,所以也许有更快的方法。
get-childitem \\$s\logs -include $filemask -recurse | select-string -pattern $regex

最佳答案

好的,这就是我的做法,它似乎有效。

$files = cmd /c "$GETFILESBAT \\$server\logs\$filemask"
foreach( $f in $files ) {
    if( $f.length -gt 0 ) {
        select-string -Path $f -pattern $regex | foreach-object { $_ }
    }
}

然后 $GETFILESBAT 指向这个:
@dir /a-d /b /s %1
@exit

我正在从 PowerShell 脚本编写和删除这个 BAT 文件,所以我猜这是一个仅限 PowerShell 的解决方案,但它不仅仅使用 PowerShell。

我的初步性能指标显示这要快一万一千倍。

我测试了 gci vs. cmd dir vs. FileIO.FileSystem.GetFiles 来自@Shawn Melton 的引用 link .

底线是,对于本地驱动器上的日常使用,GetFiles是最快的。到目前为止。 CMD DIR是可敬的。一旦您为许多文件引入了较慢的网络连接,CMD DIR略快于 GetFiles .然后Get-ChildItem ...哇,这范围从不太糟糕到可怕,具体取决于所涉及的文件数量和连接速度。

一些测试运行。我在测试中移动了 GCI 以确保结果一致。

扫描 10 次迭代 c:\windows\temp对于 *.tmp 文件
.\test.ps1 "c:\windows\temp" "*.tmp" 10
GetFiles ... 00:00:00.0570057
CMD dir  ... 00:00:00.5360536
GCI      ... 00:00:01.1391139

GetFiles 比 CMD 目录快 10 倍,而 CMD 目录本身比 GCI 快 2 倍以上。

扫描 10 次迭代 c:\windows\temp用于带有递归的 *.tmp 文件
.\test.ps1 "c:\windows\temp" "*.tmp" 10 -recurse
GetFiles ... 00:00:00.7020180
CMD dir  ... 00:00:00.7644196
GCI      ... 00:00:04.7737224

GetFiles 比 CMD 目录快一点,而且两者都比 GCI 快 7 倍。

扫描另一个域上的现场服务器以获取应用程序日志文件的 10 次迭代
.\test.ps1 "\\closeserver\logs\subdir" "appname*.*" 10
GetFiles ... 00:00:00.3590359
CMD dir  ... 00:00:00.6270627
GCI      ... 00:00:06.0796079

GetFiles 大约比 CMD 目录快 2 倍,本身比 GCI 快 10 倍。

扫描另一个域上的远程服务器以查找应用程序日志文件的一次迭代,涉及许多文件
.\test.ps1 "\\distantserver.company.com\logs\subdir" "appname.2011082*.*"
CMD dir  ... 00:00:00.3340334
GetFiles ... 00:00:00.4360436
GCI      ... 00:11:09.5525579

CMD 目录可以最快地到达带有许多文件的远程服务器,但 GetFiles 相当接近。另一方面,GCI 慢了几千倍。

两次迭代扫描另一个域上的远程服务器以查找应用程序日志文件,其中包含许多文件
.\test.ps1 "\\distantserver.company.com\logs\subdir" "appname.20110822*.*" 2
CMD dir  ... 00:00:00.9360240
GetFiles ... 00:00:01.4976384
GCI      ... 00:22:17.3068616

随着测试迭代的增加或多或少线性增加。

扫描另一个域上的远程服务器以查找应用程序日志文件的一次迭代,文件较少
.\test.ps1 "\\distantserver.company.com\logs\othersubdir" "appname.2011082*.*" 10
GetFiles ... 00:00:00.5304170
CMD dir  ... 00:00:00.6240200
GCI      ... 00:00:01.9656630

这里 GCI 还不错,GetFiles 快了 3 倍,CMD 目录紧随其后。

结论
GCI需要一个 -raw-fast不尝试做太多事情的选项。同时,GetFiles是一种健康的替代方案,只是偶尔比 CMD dir 慢一点,而且通常更快(由于生成 CMD.exe?)。

作为引用,这里是 test.ps1 代码。
param ( [string]$path, [string]$filemask, [switch]$recurse=$false, [int]$n=1 )
[reflection.assembly]::loadwithpartialname("Microsoft.VisualBasic") | Out-Null
write-host "GetFiles... " -nonewline
$dt = get-date;
for($i=0;$i -lt $n;$i++){
  if( $recurse ){ [Microsoft.VisualBasic.FileIO.FileSystem]::GetFiles( $path,
      [Microsoft.VisualBasic.FileIO.SearchOption]::SearchAllSubDirectories,$filemask
    )  | out-file ".\testfiles1.txt"}
  else{ [Microsoft.VisualBasic.FileIO.FileSystem]::GetFiles( $path,
      [Microsoft.VisualBasic.FileIO.SearchOption]::SearchTopLevelOnly,$filemask
    )  | out-file ".\testfiles1.txt" }}
$dt2=get-date;
write-host $dt2.subtract($dt)
write-host "CMD dir... " -nonewline
$dt = get-date;
for($i=0;$i -lt $n;$i++){
  if($recurse){
    cmd /c "dir /a-d /b /s $path\$filemask" | out-file ".\testfiles2.txt"}
  else{ cmd /c "dir /a-d /b $path\$filemask" | out-file ".\testfiles2.txt"}}
$dt2=get-date;
write-host $dt2.subtract($dt)
write-host "GCI... " -nonewline
$dt = get-date;
for($i=0;$i -lt $n;$i++){
  if( $recurse ) {
    get-childitem "$path\*" -include $filemask -recurse | out-file ".\testfiles0.txt"}
  else {get-childitem "$path\*" -include $filemask | out-file ".\testfiles0.txt"}}
$dt2=get-date;
write-host $dt2.subtract($dt)

关于powershell - 如何通过 UNC 加速 Powershell Get-Childitem,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7196937/

相关文章:

arrays - 为什么选择 -index 数组不起作用,powershell

powershell - Powershell-合并两个Note属性

Powershell Job "Completed"但没有完成它的任务

c# - 在 Web 应用程序中托管 PowerShell 运行空间

PowerShell - 过滤唯一值

powershell - 如何获得管道对象的数量?我不想累积管道来缓冲

powershell - 打开命令提示符以访问 USB 连接的 Windows 手机的文件夹

powershell - $MyInvocation.MyCommand.Path 在 PowerGUI 脚本编辑器中为 $null

powershell - Powershell-哈希表转义引号

mysql - 将数据库查询结果格式化为电子邮件