Эффективный подсчет файлов в каталоге и подпапках с определенным именем - PullRequest
0 голосов
/ 16 января 2019

Я могу сосчитать все файлы в папке и подпапках, сами папки не учитываются.

(gci -Path *Fill_in_path_here* -Recurse -File | where Name -like "*STB*").Count

Однако powershell слишком медленный для количества файлов (до 700 КБ). Я прочитал, что cmd быстрее выполняет такую ​​задачу.

К сожалению, я вообще не знаю кода cmd. В приведенном выше примере я считаю все файлы с STB в имени файла.

Это то, что я хотел бы сделать и в cmd.

Любая помощь приветствуется.

Ответы [ 6 ]

0 голосов
/ 19 января 2019

Общее тестирование одобряет команду MCND при запуске на нескольких системах

Результаты более 1000 запусков:

Основная информация


P/VM -          OS - PS Ver -  Files - Winner - Faster By % Seconds - Winner FPS - Loser FPS (Files Per Second)
---- - ----------- - ------ - ------ - ------ - ------------------- - ---------- - ----------------------------
 PM  - Win    7    - 5.1.1  -  87894 - SysIO  - 9%  (0.29s)         - 27,237 FPS - 24,970 FPS
 PM  - Win 2012    - 5.1.1  - 114968 - MCND   - 8%  (0.38s)         - 25,142 FPS - 23,226 FPS
 VM  - Win 2012    - 5.1.1  -  99312 - MCND   - 34% (1.57s)         - 21,265 FPS - 15,890 FPS
 PM  - Win 2016    - 5.1.1  - 102812 - SysIO  - 2%  (0.12s)         - 20,142 FPS - 19,658 FPS
 VM  - Win 2012 R2 -  4.0   -  98396 - MCND   - 29-34% (1.56-1.71s) - 19,787 FPS - 14,717 FPS
 PM  - Win 2008 R2 - 5.0.1  -  46557 - MCND   - 13-17% (0.33-0.44s) - 18,926 FPS - 16,088 FPS
 VM  - Win 2012 R2 -  4.0   -  90906 - MCND   - 22% (1.25s)         - 16,772 FPS - 13,629 FPS

Кроме того, команда Theos будет бомбить C: \ Windows, пока MCND работает как положено.

- Я объяснил MK в комментариях, что каталог \ cookies и другие подобные каталоги преднамеренно не просматриваются, так что вы не должны дважды считать файлы, содержащиеся в них.

Тест MK, выполненный на VMWare fusion поверх его MAC OS, далек от окончательного, и показывает, что время выполнения невероятно медленное, что сразу подсказало мне, что это были странные результаты.

Кроме того, я не смог выполнить команду, написанную MK, и получить результат о количестве файлов в папке, поэтому я включил в свой тест фрагмент, который показывает, что все используемые методы дают правильный результат.

Вот код, используемый для моих прогонов, обратите внимание, что я также пробежал 1000 прогонов, используя предпочтительный метод MK для сравнения результатов.

Странно, что один метод .count для команды MCND, похоже, дает очень предвзятые результаты в моей системе win7, сильно отличающийся от любой другой системы и чрезвычайно медленный (в 5 раз медленнее) в начальных прогонах, которые я выложил, и меняющийся больше в будущем пробежки я пробовал.

Но я думаю, что это связано с нагрузкой, и я планирую отбросить эти результаты, если мне когда-нибудь захочется публиковать больше, но большинство оставшихся систем довольно схожи с результатами, я чувствую, что они могут показаться излишними, если их нет. из самых разных систем.

$MaxRuns=1000
$Root_Dir="c:\windows\winsxs"
$Results_SysIO=@()
$Results_MCND1=@()
$Results_MCND2=@()
$Results_MCND3=@()
$Results_Meta=@()

FOR ($j=1; $j -le $MaxRuns; $j++) {

      Write-Progress -Activity "Testing Mthods for $MaxRuns Runs" -Status "Progress: $($j/$MaxRuns*100)% -- Run $j of $MaxRuns" -PercentComplete ($j/$MaxRuns*100) 

    # Tests  SysIO: @([System.IO.Directory]::EnumerateFiles($Root_Dir, '*', 'AllDirectories')).Count
      $Results_SysIO+=Measure-Command { @([System.IO.Directory]::EnumerateFiles($Root_Dir, '*', 'AllDirectories')).Count }
      sleep -milliseconds 500

    # Tests  MCND1 CMD Script:  DIR "%~1" /s /a-d ^| FIND /I /V "" | find /c /v ""
      $Results_MCND1+=Measure-Command {C:\Admin\TestMCNDFindFiles1.cmd $Root_Dir}
      sleep -milliseconds 500

     # Tests MCND2 CMD Count: {cmd /c 'dir /s /b /a-d $Root_Dir | find /c /v """"'}
      $Results_MCND2+=Measure-Command {cmd /c `"dir /s /b /a-d $Root_Dir `| find /c /v `"`"`"`"`"}
      sleep -milliseconds 500

     # Tests MCND3 PS Count (cmd /c dir /s /b /a-d $Root_Dir).Count
      $Results_MCND3+=Measure-Command {(cmd /c dir /s /b /a-d $Root_Dir).Count}
      sleep -milliseconds 500


}

$CPU=Get-WmiObject Win32_Processor
""
"CPU: $($($CPU.name).count)x $($CPU.name | select -first 1) - Windows: $($(Get-WmiObject Win32_OperatingSystem).Version) - PS Version: $($PSVersionTable.PSVersion)"
ForEach ($Name in "SysIO","MCND1","MCND2","MCND3") {
    $Results_Meta+=[PSCustomObject]@{
      Method=$Name
      Min=$($($(Get-Variable -Name "Results_$Name" -valueOnly).TotalSeconds|Measure-Object -Minimum).Minimum)
      Max=$($($(Get-Variable -Name "Results_$Name" -valueOnly).TotalSeconds|Measure-Object -Maximum).Maximum)
      Avg=$($($(Get-Variable -Name "Results_$Name" -valueOnly).TotalSeconds|Measure-Object -Average).Average)
    }
}

$Results_Meta | sort Avg | select Method,Min,Max,Avg,@{N="Factor";e={("{0:f2}" -f (([math]::Round($_.Avg / $($Results_Meta | sort Avg | select Avg)[0].avg,2,1))))}}|FT

Time-Command `
{cmd /c `"dir /s /b /a-d $Root_Dir `| find /c /v `"`"`"`"`"},
{C:\Admin\TestMCNDFindFiles1.cmd $Root_Dir},
{@([System.IO.Directory]::EnumerateFiles($Root_Dir, '*', 'AllDirectories')).Count},
{(cmd /c dir /s /b /a-d $Root_Dir).Count} $MaxRuns `

""
"Results of Commands - (How many Files were in that Folder?):"

[PSCustomObject]@{
    SysIO=$(&{ @([System.IO.Directory]::EnumerateFiles($Root_Dir, '*', 'AllDirectories')).Count })
    MCND1=$(&{C:\Admin\TestMCNDFindFiles1.cmd $Root_Dir})
    MCND2=$(&{cmd /c `"dir /s /b /a-d $Root_Dir `| find /c /v `"`"`"`"`"})
    MCND3=$(&{(cmd /c dir /s /b /a-d $Root_Dir).Count})
}

У меня есть дополнительные прогоны, которые я еще не собрал с дополнительных систем, хотя результаты Win7 противоречивы, поэтому я, вероятно, лишу их, когда мне нужно будет добавить в список другие системы.

Детальные выводы


Физический ноутбук Win 7 - файлы 87894 - Проигравший: MCND медленнее на 9% (.29 с) - (Метод выигрыша: 27 237 FPS) - Результаты не повторяются при повторных запусках, в то время как другие системы .

Процессор: 1x Intel® Core® TM CPU i5-4310U @ 2,00 ГГц - Windows: 6.1.7601 - Версия PS: 5.1.14409.1012


CPU: 1x Intel(R) Core(TM) i5-4310U CPU @ 2.00GHz - Windows: 6.1.7601 - PS Version: 5.1.14409.1012

Method       Min       Max          Avg Factor
------       ---       ---          --- ------
SysIO  3.0190345 6.1287085 3.2174689013 1.00  
MCND1  3.3655209 5.9024033 3.5490564665 1.10  
MCND3  3.5865989 7.5816207 3.8515160528 1.20  
MCND2  3.7542295 7.5619913 3.9471552743 1.23  
3.2174689013
0.0000366062
Command                                                                          Secs (1000-run avg.) TimeSpan         Factor
-------                                                                          -------------------- --------         ------
@([System.IO.Directory]::EnumerateFiles($Root_Dir, '*', 'AllDirectories')).Count 3.227                00:00:03.2271969 1.00  
C:\Admin\TestMCNDFindFiles1.cmd $Root_Dir                                        3.518                00:00:03.5178810 1.09  
cmd /c `"dir /s /b /a-d $Root_Dir `| find /c /v `"`"`"`"`"                       3.911                00:00:03.9106284 1.21  
(cmd /c dir /s /b /a-d $Root_Dir).Count                                          16.338               00:00:16.3377823 5.06  

Results of Commands - (How many Files were in that Folder?):

SysIO MCND1 MCND2 MCND3
----- ----- ----- -----
87894 87894 87894 87894

Физический рабочий стол Win 2012 - 114968 файлов - Проигравший: SysIO на 8% (.38с) медленнее - (метод выигрыша: 25,142 FPS)

Процессор: 1x Процессор Intel (R) Xeon (R) E5-2407 0 @ 2,20 ГГц - Windows: 6.3.9600 - Версия PS: 5.1.14409.1012


CPU: 1x Intel(R) Xeon(R) CPU E5-2407 0 @ 2.20GHz - Windows: 6.3.9600 - PS Version: 5.1.14409.1012

Method       Min        Max          Avg Factor
------       ---        ---          --- ------
MCND1  4.4957173  8.6672112 4.5726616326 1.00  
MCND3  4.6815509 18.6689706 4.7940769407 1.05  
SysIO  4.8789948  5.1625618 4.9476786004 1.08  
MCND2  5.0404912  7.2557797 5.0854683543 1.11  

Command                                                                          Secs (1000-run avg.) TimeSpan         Factor
-------                                                                          -------------------- --------         ------
C:\Admin\TestMCNDFindFiles1.cmd $Root_Dir                                        4.542                00:00:04.5418653 1.00  
(cmd /c dir /s /b /a-d $Root_Dir).Count                                          4.772                00:00:04.7719769 1.05  
@([System.IO.Directory]::EnumerateFiles($Root_Dir, '*', 'AllDirectories')).Count 4.933                00:00:04.9330404 1.09  
cmd /c `"dir /s /b /a-d $Root_Dir `| find /c /v `"`"`"`"`"                       5.086                00:00:05.0855891 1.12  

Results of Commands - (How many Files were in that Folder?):

 SysIO MCND1  MCND2   MCND3
 ----- -----  -----   -----
114968 114968 114968 114968

VM Win 2012 Server - 99312 файлов - Проигравший: SysIO на 34% (1,57 с) медленнее - (метод выигрыша: 21 265 FPS)

Процессор: 4x Intel (R) Xeon® CPU E7-2850 @ 2,00 ГГц - Windows: 6.3.9600 - Версия PS: 5.1.14409.1005


CPU: 4x Intel(R) Xeon(R) CPU E7- 2850  @ 2.00GHz - Windows: 6.3.9600 - PS Version: 5.1.14409.1005

Method       Min       Max              Avg Factor
------       ---       ---              --- ------
MCND1  4.5563908 5.2656374     4.6812307177 1.00  
MCND3  4.6696518 5.3846231     4.9064852835 1.05  
MCND2  5.0559205 5.5583717 5.15425442679999 1.10  
SysIO   6.036294 6.7952711      6.254027334 1.34  

Command                                                                          Secs (1000-run avg.) TimeSpan         Factor
-------                                                                          -------------------- --------         ------
C:\Admin\TestMCNDFindFiles1.cmd $Root_Dir                                        4.669                00:00:04.6689048 1.00  
(cmd /c dir /s /b /a-d $Root_Dir).Count                                          4.934                00:00:04.9336925 1.06  
cmd /c `"dir /s /b /a-d $Root_Dir `| find /c /v `"`"`"`"`"                       5.153                00:00:05.1532386 1.10  
@([System.IO.Directory]::EnumerateFiles($Root_Dir, '*', 'AllDirectories')).Count 6.239                00:00:06.2389727 1.34  

Results of Commands - (How many Files were in that Folder?):

SysIO MCND1 MCND2 MCND3
----- ----- ----- -----
99312 99312 99312 99312

Физический сервер Win 2016 - 102812 Файлы - Проигравший: MCND медленнее на 2% (0,12 с) - (Метод выигрыша: 20 142 FPS)

Процессор: 2x Intel (R) Xeon® CPU E5-2667 v4 @ 3,20 ГГц - Windows: 10.0.14393 - PS Версия: 5.1.14393.2608


CPU: 2x Intel(R) Xeon(R) CPU E5-2667 v4 @ 3.20GHz - Windows: 10.0.14393 - PS Version: 5.1.14393.2608

Method       Min       Max              Avg Factor
------       ---       ---              --- ------
SysIO  5.0414178 5.5279055     5.1043614001 1.00  
MCND3  5.0468476 5.4673033 5.23160342460001 1.02  
MCND1  5.1649438 5.6745749 5.26664923669999 1.03  
MCND2  5.3280266 5.7989287     5.3747728434 1.05  

Command                                                                          Secs (1000-run avg.) TimeSpan         Factor
-------                                                                          -------------------- --------         ------
@([System.IO.Directory]::EnumerateFiles($Root_Dir, '*', 'AllDirectories')).Count 5.156                00:00:05.1559628 1.00  
(cmd /c dir /s /b /a-d $Root_Dir).Count                                          5.256                00:00:05.2556244 1.02  
C:\Admin\TestMCNDFindFiles1.cmd $Root_Dir                                        5.272                00:00:05.2722298 1.02  
cmd /c `"dir /s /b /a-d $Root_Dir `| find /c /v `"`"`"`"`"                       5.375                00:00:05.3747287 1.04  

Results of Commands - (How many Files were in that Folder?):

 SysIO MCND1  MCND2   MCND3
 ----- -----  -----   -----
102812 102812 102812 102812

VM Win 2012 R2 Server - 98396 Файлы - Проигравший: SysIO 29-34% (1,56-1,71 с) Медленнее - (метод выигрыша: 19 787 FPS)

Процессор: 2x Intel (R) Xeon® процессор E7-2850 @ 2,00 ГГц - Windows: 6.3,9600 - Версия PS: 4.0


CPU: 2x Intel(R) Xeon(R) CPU E7- 2850  @ 2.00GHz - Windows: 6.3.9600 - PS Version: 4.0


Method                                                        Min                             Max                             Avg Factor                         
------                                                        ---                             ---                             --- ------                         
MCND1                                                   4.7007419                       5.9567352                4.97285509330001 1.00                           
MCND2                                                   5.2086999                       6.7678172                    5.4849721167 1.10                           
MCND3                                                   5.0116501                       8.7416729                5.71391797679999 1.15                           
SysIO                                                   6.2400687                        7.414201                    6.6862204345 1.34 

Command                                  Secs (1000-run avg.)                     TimeSpan                                Factor                                 
-------                                  --------------------                     --------                                ------                                 
C:\Admin\TestMCNDFindFiles1.cmd $Root... 5.359                                    00:00:05.3592304                        1.00                                   
cmd /c `"dir /s /b /a-d $Root_Dir `| ... 5.711                                    00:00:05.7107644                        1.07                                   
(cmd /c dir /s /b /a-d $Root_Dir).Count  6.173                                    00:00:06.1728413                        1.15                                   
@([System.IO.Directory]::EnumerateFil... 6.921                                    00:00:06.9213833                        1.29                                   

Results of Commands - (How many Files were in that Folder?):

                                   SysIO MCND1                                    MCND2                                                                     MCND3
                                    ----- -----                                    -----                                                                     -----
                                   98396 98396                                    98396                                                                     98396

Физический сервер Win 2008 R2 - 46557 файлов - Проигравший: SysIO 13-17% (0,33-0,44 с) Медленнее - (метод выигрыша: 18 926 FPS)

Процессор: 2x Intel (R) Xeon® CPU 5160 @ 3,00 ГГц - Windows: 6.1.7601 - Версия PS: 5.0.10586.117


CPU: 2x Intel(R) Xeon(R) CPU            5160  @ 3.00GHz - Windows: 6.1.7601 - PS Version: 5.0.10586.117

Method       Min       Max          Avg Factor
------       ---       ---          --- ------
MCND3  2.2370018 2.8176253 2.4653543378 1.00  
MCND1  2.4063578 2.8108379 2.5373719772 1.03  
MCND2  2.5953631 2.9085969 2.7312907064 1.11  
SysIO  2.7207865 30.335369 2.8940406601 1.17  

Command                                                                          Secs (1000-run avg.) TimeSpan         Factor
-------                                                                          -------------------- --------         ------
(cmd /c dir /s /b /a-d $Root_Dir).Count                                          2.500                00:00:02.5001477 1.00  
C:\Admin\TestMCNDFindFiles1.cmd $Root_Dir                                        2.528                00:00:02.5275259 1.01  
cmd /c `"dir /s /b /a-d $Root_Dir `| find /c /v `"`"`"`"`"                       2.726                00:00:02.7259539 1.09  
@([System.IO.Directory]::EnumerateFiles($Root_Dir, '*', 'AllDirectories')).Count 2.826                00:00:02.8259697 1.13  

Results of Commands - (How many Files were in that Folder?):

SysIO MCND1 MCND2 MCND3
----- ----- ----- -----
46557 46557 46557 46557

VMWare Win 2012 R2 Server - 90906 файлов - Проигравший: SysIO 23% (1,25 с) Медленнее - (метод выигрыша: 15,722 FPS)

Процессор: 4x Intel (R) Xeon® CPU E7-2850 @ 2,00 ГГц - Windows: 6.3,9600 - Версия PS: 4.0


CPU: 4x Intel(R) Xeon(R) CPU E7- 2850  @ 2.00GHz - Windows: 6.3.9600 - PS Version: 4.0

Method                                                        Min                             Max                             Avg Factor                         
------                                                        ---                             ---                             --- ------                         
MCND1                                                   5.0516057                       6.4537866                     5.423386317 1.00                           
MCND3                                                   5.3297157                       7.1722929                    5.9030135773 1.09                           
MCND2                                                   5.5460548                       7.0356455                     5.931334868 1.09                           
SysIO                                                   6.2059999                      19.5145373                    6.6747122712 1.23                           

Command                                  Secs (1000-run avg.)                     TimeSpan                                Factor                                 
-------                                  --------------------                     --------                                ------                                 
C:\Admin\TestMCNDFindFiles1.cmd $Root... 5.409                                    00:00:05.4092046                        1.00                                   
(cmd /c dir /s /b /a-d $Root_Dir).Count  5.936                                    00:00:05.9358832                        1.10                                   
cmd /c `"dir /s /b /a-d $Root_Dir `| ... 6.069                                    00:00:06.0689899                        1.12                                   
@([System.IO.Directory]::EnumerateFil... 6.557                                    00:00:06.5571859                        1.21                                   


Results of Commands - (How many Files were in that Folder?):

                                   SysIO MCND1                                    MCND2                                                                     MCND3
                                    ----- -----                                    -----                                                                     -----
                                   90906 90906                                    90906                                                                     90906

0 голосов
/ 17 января 2019

Полезный ответ Тео на основе прямого использования .NET ([System.IO.Directory]::EnumerateFiles()) - самый быстрый вариант (в моих тестах; YMMV - см. Тест код ниже [1] ).

Его ограничения в .NET Framework (FullCLR) - на котором Windows PowerShell - это:

  • Исключение выдается при обнаружении недоступного каталога (из-за отсутствия разрешений). Вы можете поймать исключение, но вы не можете продолжить перечисление ; то есть вы не можете точно перечислить все элементы, к которым вы можете получить доступ , игнорируя те, которые вы не можете.

  • Скрытые предметы всегда включены.

  • При рекурсивном перечислении символические ссылки / переходы к каталогам неизменно следуют.

В отличие от этого, кроссплатформенный .NET Core framework, начиная с v2.1 - на котором построен PowerShell Core - предлагает способы обойти эти ограничения через опции EnumerationOptions - см. этот ответ для примера.

Обратите внимание, что вы также можете выполнять перечисление через связанный тип [System.IO.DirectoryInfo], который - подобно Get-ChildItem - возвращает богатые объекты вместо простого строки пути, позволяющие многое для универсальной обработки; например, чтобы получить массив файлов всех размеров (свойство .Length, неявно примененное к каждому объекту файла):

([System.IO.DirectoryInfo] $somePath).EnumerateFiles('*STB*', 'AllDirectories').Length

Собственное решение PowerShell , которое устраняет эти ограничения и все еще достаточно быстрое должно использовать Get-ChildItem с параметром -Filter .

(Get-ChildItem -LiteralPath $somePath -Filter *STB* -Recurse -File).Count
  • Скрытые элементы исключены по умолчанию; добавьте -Force, чтобы включить их.

  • Чтобы игнорировать проблемы с разрешениями, добавьте -ErrorAction SilentlyContinue или -ErrorAction Ignore; Преимущество SilentlyContinue в том, что вы можете позже проверить коллекцию $Error, чтобы определить, какие именно ошибки произошли, чтобы убедиться, что ошибки действительно связаны только с проблемами прав доступа.

  • В Windows PowerShell , Get-ChildItem -Recurse неизменно , к сожалению, следует по символическим ссылкам / переходам к каталогам; более разумно то, что PowerShell Core по умолчанию поддерживает , а не и предлагает opt-in через -FollowSymlink.

  • Как и решение на основе [System.IO.DirectoryInfo], Get-ChildItem выводит многофункциональные объекты ([System.IO.FileInfo] / [System.IO.DirectoryInfo]), описывающие каждый перечисляемый элемент файловой системы, обеспечивающий универсальную обработку.

Обратите внимание, что хотя вы можете также передавать подстановочные аргументы в -Path (подразумеваемый первый позиционный параметр) и -Include (как в ответе TobyU ), только -Filter, что обеспечивает значительное улучшение скорости благодаря фильтрации в источнике (драйвер файловой системы), так что PowerShell получает только уже отфильтрованные результаты; напротив, -Path / -Include должен сначала перечислить все и сопоставить с шаблоном подстановки впоследствии . [2]

Предостережения о -Filter использовании :

  • Язык подстановочных знаков не такой же, как язык PowerShell; в частности, он не поддерживает наборы символов / диапазоны (например, *[0-9]) и имеет устаревшие особенности - см. этот ответ .
  • Он поддерживает только шаблон single wildcard, тогда как -Include поддерживает несколько (как массив).

Тем не менее, -Filter обрабатывает символы подстановки так же, как cmd.exe dir.


Наконец, для полноты картины вы можете адаптировать полезный ответ MC ND на основе cmd.exe dir команды для использования в PowerShell, что упрощает вопросы:

(cmd /c dir /s /b /a-d "$somePath/*STB*").Count

PowerShell записывает вывод stdout внешней программы в виде массива строк, количество элементов которого можно просто запросить с помощью свойства .Count (или .Length).

Тем не менее, может или не может быть быстрее, чем собственный Get-ChildItem -Filter PowerShell, в зависимости от сценария фильтрации; также обратите внимание, что dir /s может только когда-либо возвращать строки пути , тогда как Get-ChildItem возвращает расширенные объекты, свойства которых вы можете запросить.

Предостережения о dir использовании :

  • /a-d исключает каталоги, т. Е. Только файлы отчетов, но также включает в себя скрытые файлы, которые dir не делает по умолчанию.

  • dir /s неизменно спускается в скрытые каталоги также во время рекурсивного перечисления; фильтр /a (на основе атрибутов) применяется только к элементам перечисления leaf (в данном случае только к файлам ).

  • dir /s неизменно следует за символическими ссылками / соединениями с другими каталогами (при условии, что у него есть необходимые разрешения - см. Следующий пункт).

  • dir /s тихо игнорирует каталоги или символические ссылки / переходы на каталоги, если не может перечислить их содержимое из-за отсутствия разрешений - хотя это полезно в конкретном случае вышеупомянутых скрытых системных переходов (вы можете найти их все с помощью cmd /c dir C:\ /s /ashl), это может привести к тому, что вы пропустите содержимое каталогов, которые вы делаете хотите перечислить, но не сможете из-за отсутствия реальных прав доступа, потому что dir /s будет не указывайте, что такой контент может даже существовать (если вы напрямую нацелились на недоступный каталог, вы получите несколько вводящее в заблуждение сообщение об ошибке File Not Found, а код выхода установлен на 1).


Сравнение производительности:

  • В следующих тестах сравнивается производительность чистого перечисления без фильтрации , для простоты, с использованием значительного дерева каталогов, предположительно присутствующего во всех системах, c:\windows\winsxs; Тем не менее, тесты легко адаптировать для сравнения производительности фильтрации.

  • Тесты запускаются из PowerShell, что означает, что некоторые накладные расходы вводятся путем создания дочернего процесса для cmd.exe для вызова dir /s, хотя (а) эти издержки должны быть относительно низкими и (b ) важнее то, что пребывание в сфере PowerShell стоит того, учитывая его значительно превосходящие возможности по сравнению с cmd.exe.

  • В тестах используется функция Time-Command, которую можно загрузить из this Gist , в среднем по умолчанию 10 прогонов.

# Warm up the filesystem cache for the target dir.,
# both from PowerShell and cmd.exe, to be safe.
gci 'c:\windows\winsxs' -rec >$null; cmd /c dir /s 'c:\windows\winsxs' >$null

Time-Command `
  { @([System.IO.Directory]::EnumerateFiles('c:\windows\winsxs', '*', 'AllDirectories')).Count },
  { (Get-ChildItem -Force -Recurse -File 'c:\windows\winsxs').Count },
  { (cmd /c dir /s /b /a-d 'c:\windows\winsxs').Count },
  { cmd /c 'dir /s /b /a-d c:\windows\winsxs | find /c /v """"' }

На моей одноядерной виртуальной машине VMWare Fusion с Windows PowerShell v5.1.17134.407 в Microsoft Windows 10 Pro (64-разрядная; Версия 1803, сборка ОС: 17134.523) я получаю следующие временные интервалы, от самых быстрых до самых медленных (выделите право видеть столбец Factor для отображения относительной производительности):

Command                                                                                    Secs (10-run avg.) TimeSpan         Factor
-------                                                                                    ------------------ --------         ------
@([System.IO.Directory]::EnumerateFiles('c:\windows\winsxs', '*', 'AllDirectories')).Count 11.016             00:00:11.0158660 1.00
(cmd /c dir /s /b /a-d 'c:\windows\winsxs').Count                                          15.128             00:00:15.1277635 1.37
cmd /c 'dir /s /b /a-d c:\windows\winsxs | find /c /v """"'                                16.334             00:00:16.3343607 1.48
(Get-ChildItem -Force -Recurse -File 'c:\windows\winsxs').Count                            24.525             00:00:24.5254979 2.23

Интересно, что решение [System.IO.Directory]::EnumerateFiles() и Get-ChildItem значительно быстрее в PowerShell Core , который работает поверх .NET Core (начиная с PowerShell Core 6.2.0-preview.4,. NET Core 2.1):

Command                                                                                    Secs (10-run avg.) TimeSpan         Factor
-------                                                                                    ------------------ --------         ------
@([System.IO.Directory]::EnumerateFiles('c:\windows\winsxs', '*', 'AllDirectories')).Count 5.094              00:00:05.0940364 1.00
(cmd /c dir /s /b /a-d 'c:\windows\winsxs').Count                                          12.961             00:00:12.9613440 2.54
cmd /c 'dir /s /b /a-d c:\windows\winsxs | find /c /v """"'                                14.999             00:00:14.9992965 2.94
(Get-ChildItem -Force -Recurse -File 'c:\windows\winsxs').Count                            16.736             00:00:16.7357536 3.29

[1] [System.IO.Directory]::EnumerateFiles() по своей природе и, несомненно, быстрее, чем решение Get-ChildItem. В моих тестах (см. Раздел «Сравнение производительности:» выше) [System.IO.Directory]::EnumerateFiles() также побил cmd /c dir /s, немного в Windows PowerShell и явно в PowerShell Core, но другие сообщают о других выводах . Тем не менее, поиск в целом самого быстрого решения - не единственное соображение, особенно если требуется больше, чем просто подсчет файлов и если перечисление должно быть надежным . В этом ответе обсуждаются компромиссы различных решений.

[2] Фактически из-за неэффективной реализации Windows PowerShell v5.1 / PowerShell Core 6.2.0-preview.4 использование -Path и -Include на самом деле * на 1326 * медленнее , чем использовать Get-ChildItem без фильтрации и вместо этого использовать дополнительный сегмент конвейера с ... | Where-Object Name -like *STB*, как в OP - см. этот выпуск GitHub .

0 голосов
/ 16 января 2019

Одним из самых быстрых способов сделать это в cmd командной строке или командном файле может быть

dir "x:\some\where\*stb*" /s /b /a-d | find /c /v ""

Просто рекурсивная (/s) dir команда для вывода списка всех файлов (без папок /a-d) в формате bare (/b), со всеми выводами, переданными в find команда, которая посчитает (/c) количество непустых строк (/v "")

Но, в любом случае, вам нужно будет перечислить файлы, и это требует времени.

отредактировано для адаптации к комментариям, НО

note Приведенный ниже подход не работает для этого случая, поскольку, по крайней мере в окнах 10, заполнение пробелами в строках итогов команды dir установлено на пять позиций. Количество файлов, превышающее 99999, заполнено неправильно, поэтому вывод sort /r неверен.

Как указал Бен Персоник, команда dir также выводит количество файлов, и мы можем получить эту информацию:

@echo off
    setlocal enableextensions disabledelayedexpansion

    rem Configure where and what to search
    set "search=x:\some\where\*stb*"

    rem Retrieve the number of files
    set "numFiles=0"
    for /f %%a in ('
        dir "%search%" /s /a-d /w 2^>nul        %= get the list of the files        =%
        ^| findstr /r /c:"^  *[1-9]"            %= retrieve only summary lines      =%
        ^| sort /r 2^>nul                       %= reverse sort, greater line first =%
        ^| cmd /e /v /c"set /p .=&&echo(!.!"    %= retrieve only first line         =%
    ') do set "numFiles=%%a"

    echo File(s) found: %numFiles% 

Основная идея - использовать серию переданных по конвейеру команд для обработки различных частей поиска данных:

  • Используйте команду dir для генерации списка файлов (/w включена только для генерации меньшего количества строк).
  • Поскольку нам нужны только итоговые строки с количеством найденных файлов, findstr используется для извлечения только тех строк, которые начинаются с пробелов (заголовок / итоговые строки) и с числом больше 0 (итоговые строки по количеству файлов, так как мы используется /a-d, итоговые строки счетчика каталогов будут иметь значение 0).
  • Сортируйте строки в обратном порядке, чтобы закончить сначала с большей строкой (итоговые строки начинаются с отступа влево). Большая строка (итоговое число файлов или эквивалент) будет первой строкой.
  • Получить только эту строку, используя команду set /p в отдельном экземпляре cmd. Поскольку полная последовательность заключена в for /f и у нее есть проблемы с производительностью при извлечении длинных списков из выполнения команд, мы постараемся извлечь как можно меньше.

for /f токенизирует найденную строку, получает первый токен (количество файлов) и устанавливает переменную, используемую для хранения данных (переменная была инициализирована, возможно, файл не найден).

0 голосов
/ 16 января 2019

Я бы предпочел сделать PowerShell, так как это гораздо более сильный инструмент. Вы можете попробовать этот скрипт .bat file.

@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION

SET /A "N=0"
FOR /F "delims=" %%f IN ('DIR /S /B /A:-D "C:\path\to\files\*STB*"') DO (SET /A "N=!N!+1")
ECHO There are !N! files.
0 голосов
/ 16 января 2019

Я думаю, это намного быстрее:

$path = 'Fill_in_path_here'
@([System.IO.Directory]::EnumerateFiles($path, '*STB*', 'AllDirectories')).Count

Если вы не хотите возвращать подпапки, измените 'AllDirectories' на 'TopDirectoryOnly'

0 голосов
/ 16 января 2019

Вы можете ускорить процесс с PowerShell, если вы включите filter непосредственно в command вместо фильтрации result set команды, которая намного больше предварительно отфильтрованной.

Попробуйте это:

(Get-ChildItem -Path "Fill_in_path_here" -Recurse -File -Include "*STB*").Count
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...