Рекурсивний пошук файлів за допомогою 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.