好吧,這就是我如何做,它似乎工作。
$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。
我的初步性能指標表明這是更快eleventy萬倍。
我測試了gci與cmd dir與@Shawn Melton引用的FileIO.FileSystem.GetFiles link。
底線是,對於本地驅動器上的日常使用,GetFiles
是最快的。 到目前爲止。 CMD DIR
是可敬的。一旦你用很多文件引入了一個較慢的網絡連接,CMD DIR
比GetFiles
稍快。然後Get-ChildItem
......哇,這個範圍是不是太糟糕到恐怖,這取決於所涉及的文件數量和連接速度。
一些測試運行。我已經在測試中移動了GCI,以確保結果一致。
10次迭代掃描c:\windows\temp
用於* .tmp文件
.\test.ps1 "c:\windows\temp" "*.tmp" 10
GCI... 00:00:01.1391139
GetFiles... 00:00:00.0570057
CMD dir... 00:00:00.5360536
的GetFiles比CMD目錄,其本身比2倍以上GCI要快10倍。掃描c:\windows\temp
爲* .tmp文件的
10次迭代遞推
.\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 DIR快一點,而且兩者都比GCI幾乎快7倍。在另一個域掃描現場服務器應用程序日誌文件
.\test.ps1 "\\closeserver\logs\subdir" "appname*.*" 10
GCI... 00:00:06.0796079
GetFiles... 00:00:00.3590359
CMD dir... 00:00:00.6270627
的GetFiles的
10次迭代大約爲2x比CMD DIR更快,本身10倍比GCI更快。
掃描遠程服務器上的其他域的應用程序日誌文件,有許多文件的一個迭代涉及
.\test.ps1 "\\distantserver.company.com\logs\subdir" "appname.2011082*.*"
GCI... 00:11:09.5525579
GetFiles... 00:00:00.4360436
CMD dir... 00:00:00.3340334
CMD目錄最快要與許多文件的遠程服務器,但GetFiles的是體面地關閉。另一方面,GCI要慢幾千倍。
兩次迭代掃描遠程服務器上的另一域爲應用程序日誌文件,有許多文件
.\test.ps1 "\\distantserver.company.com\logs\subdir" "appname.20110822*.*" 2
GetFiles... 00:00:01.4976384
CMD dir... 00:00:00.9360240
GCI... 00:22:17.3068616
更多或更少的作爲測試迭代增加線性增加的。在另一個域掃描遠程服務器的應用程序日誌文件,以較少的文件
.\test.ps1 "\\distantserver.company.com\logs\othersubdir" "appname.2011082*.*" 10
GCI... 00:00:01.9656630
GetFiles... 00:00:00.5304170
CMD dir... 00:00:00.6240200
這裏GCI是不是太糟糕,的GetFiles的
一個迭代的3倍快,CMD dir是緊隨其後。
結論
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)
cmd.exe中的Dir一直比我曾經使用VBScript中的FileSystemObject或PS中的FileSystem提供程序的任何其他方法都快。甚至到了我已經編寫了VBScript函數來發送到cmd.exe Dir以進行文件搜索的時候。遞歸只是使其指數更明顯。 – EBGreen
也許你的PowerShell可以用像'dir/b/s \\ server \ logs \ file *。*'這樣的命令來調用CMD shell來獲取PowerShell可以輕鬆處理的表單中的完整路徑。 – ewall
@EBGreen - ''recurse'在那裏作爲一個運行反對更本地域的結轉。不是真的需要。無論有沒有它都很慢。我問這個問題的原因是(a)這是一個已知的問題,(b)很難相信PS比舊的CMD糟糕得多。 –