PowerShell kullanarak bir dizindeki dosyalar arasında geçiş yapma


243

Yalnızca tek bir dosyaya değil, dizindeki tüm .log dosyalarına bakmak için aşağıdaki kodu nasıl değiştirebilirim?

Tüm dosyalar arasında döngü ve "step4" veya "step9" içermeyen tüm satırları silmek gerekiyor. Şu anda bu yeni bir dosya oluşturacak, ancak for eachdöngüyü burada nasıl kullanacağımdan emin değilim (acemi).

Gerçek dosyalar şu şekilde adlandırılır: 2013 09 03 00_01_29.log . Çıktı dosyalarının üzerine yazmasını veya "out" eklenmiş SAME adını almasını istiyorum.

$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

Yanıtlar:


363

Bunu deneyin:

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')
}

Teşekkürler. BaseName parçası çalışmıyor (sürüm 1) - ama önce tam dosyanın bir yedek oluşturmak ve sonra özgün dosyada değişiklik yaparak başardı.
user2725402

6
V1 için, temel adı ayıklamak için aşağıdakileri kullanabilirsiniz: [io.path] :: GetFileNameWithoutExtension ($ name)
Shay Levy

Ben değiştirirseniz BaseNameile FullNameİstediğimi olsun.
M--

78

Bir dizinin içeriğini almak için kullanabilirsiniz

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

Sonra bu değişken üzerinde de döngü yapabilirsiniz:

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
}

Bunu koymanın daha kolay bir yolu foreachdöngüdür (@Soapy ve @MarkSchultheiss sayesinde):

foreach ($f in $files){
    $outfile = $f.FullName + "out" 
    Get-Content $f.FullName | Where-Object { ($_ -match 'step4' -or $_ -match 'step9') } | Set-Content $outfile
}

Bu, "out.log" adlı bir çıktı dosyası oluşturur. Her girdi dosyası için nasıl ayrı bir çıktı dosyası oluşturabilirim?
user2725402

@ user2725402 <input file name> out adlı bir girişe bağlı çıkış dosyası
ekledim

ne yaptığımı emin değilim ama bu çalışmıyor - Şimdi hiçbir çıkış dosyaları (ve hata yok): $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
Ayrıca yapabilirsinforeach ($f in Get-ChildItem "C:\Users\gerhardl\Documents\My Received Files\") { ... }
Soapy

1
veya kullanınForEach ($f in $files){...}
Mark Schultheiss

31

Belirli bir dosya türü için bir dizinin içinde özyinelemeli döngü yapmanız gerekiyorsa, docdosya türündeki tüm dosyaları filtreleyen aşağıdaki komutu kullanın

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

Filtrelemeyi birden çok türde yapmanız gerekiyorsa aşağıdaki komutu kullanın.

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

Şimdi $fileNamesdeğişken , iş mantığınızı döngüye sokabileceğiniz ve uygulayabileceğiniz bir dizi görevi görür .


Beni rahatsız eden şey, gizli ve / veya sistem dosyalarının ihmal edilmesiydi. Bunları görmek -Forceiçin Get-ChildItem parametresini kullanmanız gerekir. Dokümana docs.microsoft.com/en-us/powershell/module/… adresinden bakın .
til_b

-6

Diğer cevaplar harika, sadece eklemek istiyorum ... PowerShell'de kullanılabilir farklı bir yaklaşım: GNUWin32 araçlarını yükleyin ve satırları görüntülemek / çıktıyı dosyaya yönlendirmek için grep kullanın http://gnuwin32.sourceforge.net/

Bu, her seferinde yeni dosyanın üzerine yazar:

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

Bu, logIn dosyasının üzerine yazmanız ve verileri saklamak istemeniz durumunda günlük çıktısını ekler:

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

Not: GNUWin32 araçlarını global olarak kullanabilmek için bin klasörünü sistem yolunuza eklemeniz gerekir.


18
Bu soru Unix değil, PowerShell olarak etiketlendi
SteveC

2
Evet. Açıkçası. Alımım oldukça basitti: Windows'ta GNUWin32 araçlarını kullanabilirsiniz, bu nedenle Powershell'deki * nix araçlarını kolayca kullanabilirsiniz. İşler. Hiç kimse, cevabın tamamen Powershell'e özgü olması gerektiğini söylemedi. Ve öyle olsalar bile, Win32 Utils'i doğrudan Powershell'den çağırabilirsiniz. AFAIK mevcut ve uyumlu olanı kullanmak aslında kötü bir şey değildir.
user1628658

2
Önceki yorumumu düzenlerdim, ama 5 dakika sınırını geçtim: SteveC: Windows altında iyi çalışan GNU araçlarını kullanmanın bir şekilde Powershell'e meydan okuduğunu mu söylüyorsun? Bu bir şey. Bunu sadece Powershell'de çalışmanın kısa vadede daha verimli olabileceğini anlıyorum. Uzun vadede olasılıkların genişletilmesi aslında daha fazla değer kazanıyor. Daha fazla seçenek eklersiniz ve Cygwin gibi Linux emülatörleri olmadan tamamen Windows ve Powershell'de çalışıyorsunuz. Bu yüzden rezervasyonunuzu anlasam da katılmıyorum.
user1628658

5
Soru, kullanılabilecek diğer dillerden çok değil, PowerShell'e bakmakla ilgiliydi.
SteveC

1
Cevaplar soruya yöneliktir. Bu soru, PowerShell'de yanıt istemesi bakımından açıktı. Cevabınız bir şey yüklemek ve kullanmaktı. Ruby, vb.
Yüklemeyi önerebilirsiniz
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.