Bagaimana cara mencari string di banyak file dan mengembalikan nama file di Powershell?

303

Saya sudah mulai belajar PowerShell beberapa hari yang lalu, dan saya tidak dapat menemukan apa pun di Google yang melakukan apa yang saya butuhkan, jadi tolong ajukan pertanyaan saya.

Saya telah diminta untuk mengganti beberapa string teks menjadi beberapa file. Saya belum tentu tahu ekstensi dari file target yang mungkin dan saya juga tidak tahu lokasi mereka. Sejauh ini saya telah berhasil menjelajah ke direktori ( get-ChildItem -recurse) dan menemukan string yang saya cari dengan get-content dan select-string:

Get-ChildItem -recurse | Get-Content | Select-String -pattern "dummy"

Masalahnya adalah, saya bisa melihat kemunculan teks yang saya cari, tetapi saya tidak tahu bagaimana cara memberitahu PS untuk mengembalikan path dan nama untuk setiap file yang cocok juga.

Bagaimana saya bisa mendapatkan nama dan lokasi file yang berisi ekspresi yang saya cari?

Bluz
sumber
2
Mungkin edit pertanyaannya menjadi lebih umum. Jawaban atas pertanyaan ini tidak ada hubungannya dengan JBoss atau aplikasi Anda yang sedang Anda kerjakan tampaknya ...
Kolob Canyon
5
Saya baru saja melihat komentar Anda dan mengedit pertanyaan saya ... 2 tahun kemudian! lebih baik terlambat daripada tidak pernah ... :)
Bluz

Jawaban:

469

Ini harus memberikan lokasi file yang berisi pola Anda:

Get-ChildItem -Recurse | Select-String "dummy" -List | Select Path
jon Z
sumber
3
Bagaimana jika Anda ingin juga PINDAHKAN file-file itu? ... Saya mendapatkan kesalahan dengan ini di mana saya tidak dapat bergabung dengan | Pindahkan-Item ke akhir itu.
rud3y
6
Move-Item tidak memiliki nameparameter. Coba tambahkan| %{Move-Item $_.name <destination>}
jon Z
49
Get-ChildItem -Recurse | Select-String "dummy" -List | Select Pathmengembalikan hanya kecocokan pertama untuk setiap file sehingga mungkin sedikit lebih efisien dan menghindari kebutuhan untuk mengelompokkannya
ben
5
ada baiknya memerhatikan bahwa Anda dapat menyaring hanya untuk jenis file tertentu, katakan txtfile, jika Anda menggunakan Get-ChildItem -Recurse -Filter *.txtbukannya
Girardi
@ rud3y Saya sangat menyarankan Anda menuliskannya dalam skrip menggunakan foreachloop jika Anda melakukan operasi besar seperti itu. Menjadi sangat berbelit-belit ketika Anda mencoba melakukan semua itu pada satu baris dan sangat mudah untuk membuat kesalahan besar. Saya berbicara dari pengalaman
Kolob Canyon
75

Ada berbagai jawaban akurat di sini, tetapi di sini adalah kode paling ringkas untuk beberapa variasi berbeda. Untuk setiap variasi, baris teratas menunjukkan sintaksis lengkap dan bagian bawah menunjukkan sintaksis singkat.

Item (2) adalah bentuk jawaban yang lebih ringkas dari Jon Z dan manojlds, sedangkan item (1) setara dengan jawaban dari vikas368 dan buygrush.

  1. Daftar objek FileInfo untuk semua file yang berisi pola:

    Get-ChildItem -Recurse filespec | Where-Object { Select-String pattern $_ -Quiet }
    ls -r filespec | ? { sls pattern $_ -q }
    
  2. Daftar nama file untuk semua file yang mengandung pola:

    Get-ChildItem -Recurse filespec | Select-String pattern | Select-Object -Unique Path
    ls -r filespec | sls pattern | select -u Path
    
  3. Daftar objek FileInfo untuk semua file yang tidak mengandung pola:

    Get-ChildItem -Recurse filespec | Where-Object { !(Select-String pattern $_ -Quiet) }
    ls -r filespec | ? { !(sls pattern $_ -q) }
    
  4. Daftar nama file untuk semua file yang tidak mengandung pola:

    (Get-ChildItem -Recurse filespec | Where-Object { !(Select-String pattern $_ -Quiet) }).FullName
    (ls -r filespec | ? { !(sls pattern $_ -q) }).FullName
    
Michael Sorens
sumber
Juga, jika Anda hanya mencari File yang berisi pola di mana saja, Anda dapat menyerah setelah menemukan contoh pertama dengan menggunakan -ListparameterSelect-String
KyleMit
Saya berharap OP telah mengajukan sedikit variasi pertanyaan sehingga ini akan menjadi AA. # 1 sangat berguna dan jelas bahwa @Michael Sorens groks PS!
cBlaine
20

Ini akan menampilkan jalur, nama file, dan baris konten yang ditemukannya yang cocok dengan pola.

Get-ChildItem -Path d:\applications\*config -recurse |  Select-String -Pattern "dummy" 
pengguna5000502
sumber
Jika hanya satu baris yang dapat ditambahkan di antara hasil :)
cladelpino
15

Pipa konten Anda

Get-ChildItem -recurse | Get-Content | Select-String -pattern "dummy"

untuk fl *

Anda akan melihat bahwa path sudah dikembalikan sebagai properti dari objek.

JIKA Anda hanya ingin path, gunakan select pathatau select -unique pathuntuk menghapus duplikat:

Get-ChildItem -recurse | Get-Content | Select-String -pattern "dummy" | select -unique path
manojlds
sumber
1
Terima kasih untuk kalian berdua, inilah tepatnya yang saya cari. Sayangnya, ketika ada banyak subdirektori yang terlibat dalam path, maka PS memotong path absolut dan menambahkan tiga titik di akhir baris seperti \ dir1 \ dir2 \ dir3 \ path ... jadi saya tidak tahu file mana yang dikembalikan . Apakah ada cara untuk memberitahu PS agar tidak serakah pada karakter dan repot-repot menampilkan path lengkap? :) Terima kasih banyak !
Bluz
3
Anda perlu menambahkan -Filesakelar ke Get-ChildItematau Anda berakhir dengan kaskade kesalahan yang tidak pernah berakhir untuk mencoba memanggil Get-Contentdirektori.
RubberDuck
Jika Anda memerlukan path lengkap, Anda dapat melakukan ini. (Get-ChildItem -recurse | Get-Content | Select-String -pattern "dummy").FullNameOrang tampaknya lupa bahwa PowerShell berorientasi objek; ketika ragu, cari properti
Kolob Canyon
10

Inilah yang akan saya lakukan, Anda tidak perlu mendapatkan konten:

ls -r | Select-String dummy | select line,path

atau

ls -r | Select-String dummy | fl *

Untuk melihat sifat-sifat yang berbeda itu ...

Ini lebih cepat. Argumen kedua adalah -filter:

ls -r . *.bat | select-string netsh
js2010
sumber
2
+1, Ini berfungsi dengan baik untuk kasus saya, namun gunakan select Pattern, LineNumber, Filenameuntuk output yang lebih ringkas. Baris mengembalikan SEMUA yang ada pada baris yang berisi string pola Anda. Anda juga dapat dengan mudah menampilkan ini ke csv jika Anda mau.
Protonova
9
Get-ChildItem -r | ? {$_.psiscontainer -eq $false} | ? {gc $_.pspath |select-string -pattern "dummy"}

Ini akan memberi Anda detail lengkap dari semua file

vikas368
sumber
Sama sekali tidak tahu itu -rberhasil. Mengira Anda harus selalu melakukannya-Recurse
Kolob Canyon
5

Untuk menjaga detail file lengkap dalam array yang dihasilkan, Anda dapat menggunakan sedikit modifikasi dari jawaban yang diposting oleh vikas368 (yang tampaknya tidak berfungsi dengan baik dengan ISE autocomplete):

Get-ChildItem -Recurse | Where-Object { $_ | Select-String -Pattern "dummy" }

atau singkatnya:

ls -r | ?{ $_ | Select-String -Pattern "dummy" }
buygrush
sumber
5

Jika Anda mencari di satu direktori, Anda dapat melakukannya:

select-string -Path "c:\temp\*.*" -Pattern "result"  -List | select Path
Esperento57
sumber
4

Ini akan menampilkan daftar path lengkap ke setiap file yang berisi string pencarian:

foreach ($file in Get-ChildItem | Select-String -pattern "dummy" | Select-Object -Unique path) {$file.path}

Perhatikan bahwa itu tidak menampilkan header di atas hasil dan tidak menampilkan baris teks yang berisi string pencarian. Semua itu memberitahu Anda di mana Anda dapat menemukan file yang berisi string.

Gadis Kecil
sumber
2
Adakah yang tahu bagaimana menampilkan nomor baris di mana pola ditemukan, bersama dengan nama file?
Piotr L
4

Saya memodifikasi salah satu jawaban di atas untuk memberi saya informasi lebih banyak. Ini memberi saya pertanyaan kedua nanti. Itu seperti ini:

Get-ChildItem `
        -Path "C:\data\path" -Filter "Example*.dat" -recurse | `
    Select-String -pattern "dummy" | `
    Select-Object -Property Path,LineNumber,Line | `
    Export-CSV "C:\ResultFile.csv"

Saya dapat menentukan path dan file wildcard dengan struktur ini, dan menyimpan nama file, nomor baris dan baris yang relevan ke file output.

RenoGreg
sumber
Keren! Terima kasih atas solusi tambahan ini :) Namun, bisakah Anda menautkan ke jawaban yang menjadi dasar solusi Anda dan beri nama pembuat jawaban itu untuk memberikan kredit? Terima kasih!
Max Vollmer