Rekurencyjne wyszukiwanie plików za pomocą PowerShell


238

Szukam pliku we wszystkich folderach.

Copyforbuild.bat jest dostępny w wielu miejscach i chciałbym szukać rekurencyjnie.

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

Jak mogę to zrobić w PowerShell?

Odpowiedzi:


393

Użyj polecenia cmdlet Get-ChildItem z -Recurseprzełącznikiem:

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

1
Wydaje się, że występuje problem polegający na tym, że jeśli działa w katalogu, do którego nie masz uprawnień dostępu, całe wyszukiwanie zostaje przerwane, ponieważ proces kończy się. Czy jest na to jakiś sposób?
deed02392

6
Spróbuj ustawić parametr ErrorAction na Kontynuuj lub Kontynuuj dyskretnie (w przypadku gdy jego wartość nie jest zgodna z podaną).
Shay Levy,

22
Krótszy sposób na zrobienie dokładnie tego samego: cd V:\MyFoldernastępniels -r -inc CopyForBuild.bat
Orion Edwards

8
Tak więc powyżsi komentatorzy mają na myśli ...ls -r -ea silentlycontinue -fo -inc "filename.txt" | % { $_.fullname }
Andrew

Dostosowałem tę odpowiedź do częściowego ciągu, dodając symbol astryczny ( *) na końcu nazwy pliku. ****** 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

Używam tego, aby znaleźć pliki, a następnie PowerShell wyświetla całą ścieżkę wyników:

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

Zawsze możesz użyć symbolu wieloznacznego *w FolderNamei / lub FileName.fileExtension. Na przykład:

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

Powyższy przykład przeszuka dowolny folder na C:\dysku, zaczynając od słowa Folder. Więc jeśli masz folder o nazwie FolderFooiFolderBar PowerShell wyświetli wyniki z obu tych folderów.

To samo dotyczy nazwy i rozszerzenia pliku. Jeśli chcesz wyszukać plik z określonym rozszerzeniem, ale nie znasz nazwy pliku, możesz użyć:

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

Lub odwrotnie:

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

4
Uważam, że ta odpowiedź jest bardzo przydatna, ponieważ dotyczy konkretnego przypadku użycia - w rzeczywistości chce użyć pliku, którego szukasz. The | aby dać Ci pełną nazwę pliku, brakuje czegoś w innych odpowiedziach.
Newteq Developer

1
Muszę się zgodzić z @ Sanity1123 tutaj, jeśli naprawdę chcesz użyć pliku, będziesz potrzebować pełnej ścieżki do pliku. IMHO powinna to być zaakceptowana odpowiedź.
uceumern

31

Podczas wyszukiwania folderów, w których może wystąpić błąd związany z bezpieczeństwem (np. C:\Users), Użyj następującego polecenia:

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

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

Będzie również działać


A jeśli chcesz wyprowadzać wyniki do pliku, możesz dodać `> ścieżka_do_pliku.txt` na końcu polecenia.
Gwen Au

7

Oto metoda, którą w końcu wymyśliłem po zmaganiu:

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

Aby wyczyścić dane wyjściowe (tylko ścieżka), użyj:

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

Aby uzyskać tylko pierwszy wynik, użyj:

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

Teraz najważniejsze rzeczy:

Aby wyszukiwać tylko pliki / katalogi, nie używaj -Filelub -Directory(patrz poniżej dlaczego). Zamiast tego użyj tego dla plików:

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

i usuń -eq $falsekatalogi. Czy nie zostawić z tyłu wieloznaczny podobnego bin/*.

Dlaczego nie skorzystać z wbudowanych przełączników? Są okropne i losowo usuwają funkcje. Na przykład, aby użyć -Includez plikiem, musisz zakończyć ścieżkę znakiem wieloznacznym. Jednak powoduje to wyłączenie -Recurseprzełącznika bez mówienia:

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

Można by pomyśleć, że dałoby to wszystkie *.libs we wszystkich podkatalogach, ale przeszukuje tylko najwyższy poziom bin.

Aby wyszukać katalogi, możesz użyć -Directory, ale musisz usunąć końcowy znak zastępczy. Z jakiegokolwiek powodu nie spowoduje to dezaktywacji -Recurse. Z tych powodów polecam nie używać wbudowanych flag.

Możesz znacznie skrócić to polecenie:

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

staje się

gci './path*/' -s -Include 'name*' | where {$_.PSIsContainer -eq $false}
  • Get-ChildItem jest aliasowany do gci
  • -Path jest ustawiona domyślnie na pozycję 0, więc możesz po prostu utworzyć ścieżkę pierwszego argumentu
  • -Recurse jest aliasowany do -s
  • -Include nie ma stenografii
  • Używaj pojedynczych cudzysłowów dla spacji w nazwach / ścieżkach, aby można było otoczyć całe polecenie podwójnymi cudzysłowami i używać go w wierszu polecenia. Robienie tego na odwrót (otaczanie pojedynczymi cudzysłowami) powoduje błędy

6

Spróbuj tego:

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

2
Możesz także użyć | Where-Object { !$_PSIsContainer }do wykluczenia folderów
Gargravarr

5

Filtruj za pomocą symboli wieloznacznych:

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

Filtrowanie przy użyciu wyrażenia regularnego:

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

1
Nie powinno tak być '\ACopyForBuild\.(bat|cmd)\Z'?
E. Sundin,

1

Aby dodać do odpowiedzi @ user3303020 i wyświetlić wyniki wyszukiwania w pliku, możesz uruchomić

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

W ten sposób łatwiej będzie wyszukać poprawny plik.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.