Рекурсивний пошук файлів за допомогою PowerShell


238

Я шукаю файл у всіх папках.

Copyforbuild.bat є в багатьох місцях, і я хотів би здійснити рекурсивний пошук.

$File = "V:\Myfolder\**\*.CopyForbuild.bat"

Як я можу це зробити в PowerShell?

Відповіді:


393

Використовуйте командлет Get-ChildItem з -Recurseперемикачем:

Get-ChildItem -Path V:\Myfolder -Filter CopyForbuild.bat -Recurse -ErrorAction SilentlyContinue -Force

1
Здається, виникла проблема, що якщо він потрапляє в каталог, у вас немає дозволу на доступ, весь пошук припиняється, оскільки процес закінчується. Чи є шлях до цього?
— de0202392

6
Спробуйте встановити параметр ErrorAction на «Продовжити» або «SilentlyContinue» (якщо його значення не є зазначеним).
— Шей Леві

22
Коротший спосіб робити саме те саме: cd V:\MyFolderдаліls -r -inc CopyForBuild.bat
— Orion Edwards

8
Тож, що означають коментатори вище, це ...ls -r -ea silentlycontinue -fo -inc "filename.txt" | % { $_.fullname }
— Андрій

Я адаптував цю відповідь, щоб зробити частковий рядок, додавши астричний символ ( *) до кінця імені файла. ****** LINE1: $File = "Microsoft.OData.Core.NetFX35.V7*"LINE2: $Folder = "C:\Program Files"LINE3:Get-ChildItem -Path $Folder -Filter $File -Recurse -ErrorAction SilentlyContinue -Force
— SherlockSpreadsheets

37

Я використовую це для пошуку файлів, а потім PowerShell відображає весь шлях результатів:

dir -Path C:\FolderName -Filter FileName.fileExtension -Recurse | %{$_.FullName}

Ви завжди можете використовувати підстановку *у FolderNameта / або FileName.fileExtension. Наприклад:

dir -Path C:\Folder* -Filter File*.file* -Recurse | %{$_.FullName}

У наведеному вище прикладі буде шукати будь-яку папку на C:\диску, що починається зі слова Folder. Так що якщо у вас є папка з ім'ям FolderFooі FolderBarPowerShell покаже результати обох цих папок.

Те саме стосується імені файлу та розширення файлу. Якщо ви хочете шукати файл з певним розширенням, але не знаєте його ім'я, ви можете використовувати:

dir -Path C:\FolderName -Filter *.fileExtension -Recurse | %{$_.FullName}

Або навпаки:

dir -Path C:\FolderName -Filter FileName.* -Recurse | %{$_.FullName}

4
Я вважаю цю відповідь надзвичайно корисною, оскільки вона стосується конкретного випадку використання - насправді хочеться використовувати той файл, який ви шукаєте. | щоб дати вам повне ім'я файлу, чогось не вистачає в інших відповідях.
— Newteq Developer

1
Я маю згоду з @ Sanity1123 тут, якщо ви дійсно хочете використовувати файл, вам знадобиться повний шлях до файлу. ІМХО, це має бути прийнятою відповіддю.
— uceumern

31

Під час пошуку папок, де ви можете отримати помилку на основі безпеки (наприклад C:\Users), скористайтеся такою командою:

Get-ChildItem -Path V:\Myfolder -Filter CopyForbuild.bat -Recurse -ErrorAction SilentlyContinue -Force

12
Get-ChildItem V:\MyFolder -name -recurse *.CopyForbuild.bat

Також буде працювати


І якщо ви хочете вивести результати у файл, ви можете додати `> path_to_filename.txt` в кінці команди.
— Гвен Ау

7

Ось метод, який я нарешті придумав після боротьби:

Get-ChildItem -Recurse -Path path/with/wildc*rds/ -Include file.*

Щоб зробити висновок чистішим (лише шлях), використовуйте:

(Get-ChildItem -Recurse -Path path/with/wildc*rds/ -Include file.*).fullname

Щоб отримати лише перший результат, використовуйте:

(Get-ChildItem -Recurse -Path path/with/wildc*rds/ -Include file.*).fullname | Select -First 1

Тепер про важливі речі:

Для пошуку лише файлів / каталогів не використовуйте -Fileабо -Directory(див. Нижче, чому). Замість цього використовуйте це для файлів:

Get-ChildItem -Recurse -Path ./path*/ -Include name* | where {$_.PSIsContainer -eq $false}

і видаліть -eq $falseкаталоги. Ви НЕ залишити косою символ типу bin/*.

Чому б не використовувати вбудовані вимикачі? Вони жахливі і вилучають функції випадковим чином. Наприклад, щоб використовувати -Includeз файлом, ви повинні закінчити шлях з підстановкою. Однак це вимикає -Recurseкомутатор, не повідомляючи вам:

Get-ChildItem -File -Recurse -Path ./bin/* -Include *.lib

Ви б могли подумати, що це дасть вам усі *.libs у всіх підкаталогах, але це буде лише пошук верхнього рівня bin.

Для пошуку каталогів ви можете скористатися -Directory, але тоді ви повинні видалити останню підстановку. З будь-якої причини це не вимкнеться -Recurse. Саме з цих причин я рекомендую не використовувати вбудовані прапори.

Ви можете значно скоротити цю команду:

Get-ChildItem -Recurse -Path ./path*/ -Include name* | where {$_.PSIsContainer -eq $false}

стає

gci './path*/' -s -Include 'name*' | where {$_.PSIsContainer -eq $false}
  • Get-ChildItem чужий gci
  • -Path за замовчуванням для позиції 0, тому ви можете просто зробити перший шлях аргументу
  • -Recurse чужий -s
  • -Include не має стенограми
  • Використовуйте одиничні лапки для пробілів в іменах / шляхах, щоб ви могли оточити всю команду подвійними лапки і використовувати її в командному рядку. Якщо це зробити навпаки (оточити окремими цитатами), це призводить до помилок

6

Спробуйте це:

Get-ChildItem -Path V:\Myfolder -Filter CopyForbuild.bat -Recurse | Where-Object { $_.Attributes -ne "Directory"}

2
Ви також | Where-Object { !$_PSIsContainer }можете виключити папки
— Gargravarr

5

Фільтрування за допомогою макетів:

Get-ChildItem -Filter CopyForBuild* -Include *.bat,*.cmd -Exclude *.old.cmd,*.old.bat -Recurse

Фільтрування за допомогою регулярного виразу:

Get-ChildItem -Path "V:\Myfolder" -Recurse
| Where-Object { $_.Name -match '\ACopyForBuild\.[(bat)|(cmd)]\Z' }

1
Чи не повинно бути '\ACopyForBuild\.(bat|cmd)\Z'?
— Е. Сундін

1

Щоб додати до @ user3303020 відповідь і вивести результати пошуку у файл, можна запустити

Get-ChildItem V:\MyFolder -name -recurse *.CopyForbuild.bat > path_to_results_filename.txt

Шукати правильний файл таким чином може бути простіше.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.