Хорошо, вот как я это делаю, и, похоже, работает.
$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
Я пишу и удаляю этот BAT-файл из скрипта PowerShell, поэтому я полагаю, что это решение только для PowerShell, но оно не использует только PowerShell.
Мои предварительные показатели эффективности показывают, что это в одиннадцать тысяч раз быстрее.
Я тестировал gci против cmd dir и 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
GCI... 00:00:01.1391139
GetFiles... 00:00:00.0570057
CMD dir... 00:00:00.5360536
GetFiles в 10 раз быстрее CMD dir, что само по себе более чем в 2 раза быстрее, чем GCI.
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 dir, и оба почти в 7 раз быстрее, чем GCI.
10 итераций сканирования локального сервера в другом домене на наличие файлов журнала приложений
.\test.ps1 "\\closeserver\logs\subdir" "appname*.*" 10
GCI... 00:00:06.0796079
GetFiles... 00:00:00.3590359
CMD dir... 00:00:00.6270627
GetFiles примерно в 2 раза быстрее, чем 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 dir быстрее всего отправляется на удаленный сервер со многими файлами, но 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)