Loop melalui file dalam direktori menggunakan PowerShell

243

Bagaimana saya bisa mengubah kode berikut untuk melihat semua file .log di direktori dan bukan hanya satu file?

Saya perlu mengulang semua file dan menghapus semua baris yang tidak mengandung "step4" atau "step9". Saat ini ini akan membuat file baru, tapi saya tidak yakin bagaimana menggunakan for eachloop di sini (pemula).

File sebenarnya diberi nama seperti ini: 2013 09 03 00_01_29.log . Saya ingin file output untuk ditimpa, atau memiliki nama SAMA, ditambahkan dengan "keluar".

$In = "C:\Users\gerhardl\Documents\My Received Files\Test_In.log"
$Out = "C:\Users\gerhardl\Documents\My Received Files\Test_Out.log"
$Files = "C:\Users\gerhardl\Documents\My Received Files\"

Get-Content $In | Where-Object {$_ -match 'step4' -or $_ -match 'step9'} | `
Set-Content $Out
pengguna2725402
sumber

Jawaban:

363

Cobalah ini:

Get-ChildItem "C:\Users\gerhardl\Documents\My Received Files" -Filter *.log | 
Foreach-Object {
    $content = Get-Content $_.FullName

    #filter and save content to the original file
    $content | Where-Object {$_ -match 'step[49]'} | Set-Content $_.FullName

    #filter and save content to a new file 
    $content | Where-Object {$_ -match 'step[49]'} | Set-Content ($_.BaseName + '_out.log')
}
Shay Levy
sumber
Terima kasih. Bagian BaseName tidak berfungsi (versi 1) - tetapi saya berhasil dengan terlebih dahulu membuat cadangan file lengkap kemudian membuat perubahan ke file asli.
user2725402
6
Untuk v1, Anda dapat menggunakan yang berikut ini untuk mengekstrak nama dasar: [io.path] :: GetFileNameWithoutExtension ($ name)
Shay Levy
Jika saya ganti BaseNamedengan FullNamesaya mendapatkan apa yang saya inginkan.
M--
78

Untuk mendapatkan konten direktori yang bisa Anda gunakan

$files = Get-ChildItem "C:\Users\gerhardl\Documents\My Received Files\"

Kemudian Anda dapat mengulangi variabel ini juga:

for ($i=0; $i -lt $files.Count; $i++) {
    $outfile = $files[$i].FullName + "out" 
    Get-Content $files[$i].FullName | Where-Object { ($_ -match 'step4' -or $_ -match 'step9') } | Set-Content $outfile
}

Cara yang lebih mudah untuk menempatkan ini adalah foreachloop (terima kasih kepada @Soapy dan @MarkSchultheiss):

foreach ($f in $files){
    $outfile = $f.FullName + "out" 
    Get-Content $f.FullName | Where-Object { ($_ -match 'step4' -or $_ -match 'step9') } | Set-Content $outfile
}
PVTT
sumber
Ini menciptakan satu file keluaran bernama "out.log". Bagaimana saya bisa membuat file output terpisah untuk setiap file input?
user2725402
@ user2725402 Saya menambahkan file output dependend input yang bernama <input file name> out
PVitt
tidak yakin apa yang saya lakukan salah tetapi ini tidak berfungsi - Saya sekarang tidak mendapatkan file output (dan tidak ada kesalahan): $files = Get-ChildItem "C:\Users\gerhardl\Documents\My Received Files\" $files | Where-Object { $outFile = $_.Name + "out" Get-Content $_.FullName | Where-Object { $_ -match 'step4' -or $_ -match 'step9' } | Set-Content $outFile }
user2725402
2
Anda juga dapat melakukannyaforeach ($f in Get-ChildItem "C:\Users\gerhardl\Documents\My Received Files\") { ... }
Soapy
1
atau gunakanForEach ($f in $files){...}
Mark Schultheiss
31

Jika Anda perlu mengulang di dalam direktori secara rekursif untuk jenis file tertentu, gunakan perintah di bawah ini, yang memfilter semua docfile tipe file

$fileNames = Get-ChildItem -Path $scriptPath -Recurse -Include *.doc

Jika Anda perlu melakukan penyaringan pada beberapa jenis, gunakan perintah di bawah ini.

$fileNames = Get-ChildItem -Path $scriptPath -Recurse -Include *.doc,*.pdf

Sekarang $fileNamesvariabel bertindak sebagai array yang darinya Anda dapat mengulang dan menerapkan logika bisnis Anda.

Sarath Avanavu
sumber
Apa yang mengganggu saya adalah penghapusan file tersembunyi dan / atau sistem. Untuk melihatnya, Anda harus menggunakan -Forceparameter untuk Get-ChildItem. Lihat dokumennya di docs.microsoft.com/en-us/powershell/module/… .
til_b
-6

Jawaban lain sangat bagus, saya hanya ingin menambahkan ... pendekatan berbeda yang dapat digunakan di PowerShell: Instal utils GNUWin32 dan gunakan grep untuk melihat baris / mengarahkan output ke file http://gnuwin32.sourceforge.net/

Ini menimpa file baru setiap kali:

grep "step[49]" logIn.log > logOut.log 

Ini menambahkan output log, jika Anda menimpa file logIn dan ingin menyimpan data:

grep "step[49]" logIn.log >> logOut.log 

Catatan: untuk dapat menggunakan utils GNUWin32 secara global Anda harus menambahkan folder bin ke jalur sistem Anda.

pengguna1628658
sumber
18
Pertanyaan ini ditandai sebagai PowerShell, bukan Unix
SteveC
2
Iya. Jelas sekali. Pendapat saya cukup sederhana: Anda dapat menggunakan utils GNUWin32 di Windows karena itu Anda dapat menggunakan alat * nix di Powershell dengan mudah. Bekerja Tidak ada yang pernah mengatakan, bahwa jawabannya harus sepenuhnya berasal dari Powershell. Dan bahkan jika mereka melakukannya, Anda masih dapat memanggil Utilitas Win32 langsung dari Powershell. AFAIK menggunakan apa pun yang tersedia dan kompatibel sebenarnya bukan hal yang buruk.
user1628658
2
Saya akan mengedit komentar saya sebelumnya, tetapi saya melewati batas 5 menit: SteveC: Apakah Anda mengatakan bahwa menggabungkan alat GNU yang bekerja dengan baik di Windows entah bagaimana menentang Powershell? Itu satu hal. Saya mengerti bahwa mengerjakan ini murni di Powershell mungkin lebih produktif dalam jangka pendek. Dalam jangka panjang memperluas kemungkinan sebenarnya lebih pantas. Anda menambahkan lebih banyak opsi dan bekerja sepenuhnya di Windows dan Powershell tanpa emulator Linux seperti Cygwin. Jadi sementara saya mengerti reservasi Anda, saya tidak setuju.
user1628658
5
Pertanyaannya adalah tentang mencari di PowerShell, bukan banyak bahasa lain yang bisa digunakan.
SteveC
1
Jawaban dimaksudkan untuk pertanyaan itu. Pertanyaan ini eksplisit karena menginginkan jawaban di PowerShell. Jawaban Anda adalah menginstal sesuatu dan menggunakannya. Anda bisa menyarankan untuk menginstal Ruby, dll.
SteveC