Рекурсивный поиск файлов с помощью PowerShell

238

Я ищу файл во всех папках.

Copyforbuild.bat доступно во многих местах, и я хотел бы искать рекурсивно.

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

Как я могу сделать это в PowerShell?

Samselvaprabu
источник

Ответы:

393

Используйте командлет Get-ChildItem с -Recurseпереключателем:

Get-ChildItem -Path V:\Myfolder -Filter CopyForbuild.bat -Recurse -ErrorAction SilentlyContinue -Force
Шей Леви
источник
1
Кажется, есть проблема в том, что если он попадает в каталог, к которому у вас нет прав доступа, весь поиск прерывается, потому что процесс завершается. Есть ли способ обойти это?
deed02392
6
Попробуйте установить для параметра ErrorAction значение Continue или 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}
BinaryJoe01
источник
4
Я считаю этот ответ чрезвычайно полезным, потому что он адресован конкретному случаю использования - фактически желая использовать файл, который вы ищете. | чтобы дать вам полное имя файла чего-то не хватает в других ответах.
Разработчик
1
Я должен согласиться с @ Sanity1123 здесь, если вы действительно хотите использовать файл, вам потребуется полный путь к файлу. ИМХО это должен быть принятый ответ.
Uceumern
31

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

Get-ChildItem -Path V:\Myfolder -Filter CopyForbuild.bat -Recurse -ErrorAction SilentlyContinue -Force
Motz
источник
12
Get-ChildItem V:\MyFolder -name -recurse *.CopyForbuild.bat

Тоже будет работать

user3303020
источник
И если вы хотите вывести результаты в файл, вы можете добавить `> 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 не имеет стенографии
  • Используйте одинарные кавычки для пробелов в именах / путях, чтобы вы могли заключить всю команду в двойные кавычки и использовать ее в командной строке. Если сделать это наоборот (заключить в одинарные кавычки), это приведет к ошибкам
HLK
источник
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' }
MovGP0
источник
1
Не должно ли это быть '\ACopyForBuild\.(bat|cmd)\Z'?
Э. Сундин
1

Чтобы добавить к @ user3303020 ответ и вывести результаты поиска в файл, вы можете запустить

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

Таким образом, может быть проще найти правильный файл.

Гвен Ау
источник