PowerShellを使用してディレクトリ内のファイルをループする


243

次のコードを変更して、1つのファイルだけでなく、ディレクトリ内のすべての.logファイルを確認するにはどうすればよいですか?

すべてのファイルをループして、「step4」または「step9」を含まないすべての行を削除する必要があります。現在、これは新しいファイルを作成しますが、for eachここでループを使用する方法がわかりません(初心者)。

実際のファイルの名前は、2013 09 03 00_01_29.logです。出力ファイルを上書きするか、同じ名前に「out」を付加したものにしてください。

$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

回答:


363

これを試してみてください:

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

ありがとう。BaseNameの部分は機能しません(バージョン1)。ただし、最初に完全なファイルのバックアップを作成し、次に元のファイルに変更を加えることで管理しました。
user2725402 2013

6
v1の場合、次を使用してベース名を抽出できます:[io.path] :: GetFileNameWithoutExtension($ name)
Shay Levy

私が交換した場合BaseNameFullName、私は私が欲しいものを手に入れます。
M-- 2018年

77

使用できるディレクトリのコンテンツを取得するには

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

次に、この変数をループすることもできます。

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
}

これを配置するさらに簡単な方法はforeachループです(@Soapyおよび@MarkSchultheissに感謝):

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

これにより、「out.log」という名前の出力ファイルが1つ作成されます。入力ファイルごとに個別の出力ファイルを作成するにはどうすればよいですか?
user2725402 2013

@ user2725402 <入力ファイル名> outという名前の入力依存出力ファイルを追加しました
PVitt

私が間違っていることは$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 }
わかり

2
次のこともできますforeach ($f in Get-ChildItem "C:\Users\gerhardl\Documents\My Received Files\") { ... }
Soapy

1
または使用ForEach ($f in $files){...}
Mark Schultheiss、2018年

31

特定の種類のファイルに対してディレクトリ内を再帰的にループする必要がある場合は、以下のコマンドを使用して、docファイルタイプのすべてのファイルをフィルタリングします

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

複数のタイプでフィルタリングを行う必要がある場合は、以下のコマンドを使用します。

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

これで、$fileNames変数は配列として機能し、そこからループしてビジネスロジックを適用できます。


私を悩ませたのは、隠しファイルやシステムファイルの省略です。それらも表示するには-Force、Get-ChildItemのパラメーターを使用する必要があります。docs.microsoft.com/en-us/powershell/module/…にあるドキュメントを参照してください。
til_b

-6

他の答えは素晴らしいです、私は追加したいだけです... PowerShellで使用可能な別のアプローチ:GNUWin32 utilsをインストールし、grepを使用して行を表示する/出力をファイルhttp://gnuwin32.sourceforge.net/にリダイレクトする

これにより、毎回新しいファイルが上書きされます。

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

これにより、logInファイルを上書きしてデータを保持する場合に備えて、ログ出力が追加されます。

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

注:GNUWin32 utilsをグローバルに使用するには、binフォルダーをシステムパスに追加する必要があります。


18
この質問はUnixではなくPowerShellとしてタグ付けされていました
SteveC

2
はい。明らかに。私の見解はかなり簡単でした。GNUWin32ユーティリティをWindowsで使用できるため、Powershellで* nixツールを簡単に使用できます。動作します。答えはPowershellに完全にネイティブである必要があると誰も言ったことはありません。たとえそうであっても、Powershellから直接Win32 Utilsを呼び出すことができます。入手可能で互換性のあるものを使用するAFAIKは、実際には悪いことではありません。
user1628658 2017年

2
私は以前のコメントを編集したのですが、5分の制限を超えました。それは一つのことです。純粋にPowershellでこれを実行すると、短期的には生産性が向上することを理解しています。長期的には、可能性を広げることは実際にはよりメリットがあります。さらにオプションを追加し、CygwinのようなLinuxエミュレーターなしで完全にWindowsおよびPowershellで作業します。予約を理解しましたが、同意しません。
user1628658

5
問題は、PowerShellを調べることであり、使用できる他の多数の言語ではありませんでした。
SteveC

1
回答は質問に対するものです。この質問は、PowerShellでの回答が必要であるという点で明確でした。あなたの答えは何かをインストールしてそれを使うことでした。Rubyなどのインストールを提案できます
SteveC
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.