360

How can I change the following code to look at all the .log files in the directory and not just the one file?

I need to loop through all the files and delete all lines that do not contain "step4" or "step9". Currently this will create a new file, but I'm not sure how to use the for each loop here (newbie).

The actual files are named like this: 2013 09 03 00_01_29.log. I'd like the output files to either overwrite them, or to have the SAME name, appended with "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 

3 Answers 3

518

Give this a try:

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') } 
Sign up to request clarification or add additional context in comments.

3 Comments

thanks. The BaseName part does not work (version 1) - but I managed by first creating a backup of the full file then making the change to the original file.
For v1, you can use the following to extract the base name: [io.path]::GetFileNameWithoutExtension($name)
If I replace BaseName with FullName I get what I want.
148

To get the content of a directory you can use

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

Then you can loop over this variable as well:

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 } 

An even easier way to put this is the foreach loop (thanks to @Soapy and @MarkSchultheiss):

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

8 Comments

This creates one output file named "out.log". How can I create a separate output file for each input file?
@user2725402 I added an input dependend output file that is named <input file name>out
okay 2 new issues... this now for some reason does the opposite of the match, i.e. it creates a file with only records NOT containing "step4" or "step9". Also, it is renaming using "out" as an extension, so files are named "XXX.log.out" - I tried using BaseName but can't get it right.
You can also do foreach ($f in Get-ChildItem "C:\Users\gerhardl\Documents\My Received Files\") { ... }
or use ForEach ($f in $files){...}
|
47

If you need to loop inside a directory recursively for a particular kind of file, use the below command, which filters all the files of doc file type

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

If you need to do the filteration on multiple types, use the below command.

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

Now $fileNames variable act as an array from which you can loop and apply your business logic.

2 Comments

What bugged me was the omission of hidden and/or system files. To also see them you have to use the -Force parameter to Get-ChildItem. See its doc at learn.microsoft.com/en-us/powershell/module/… .
Note: The Include parameter only works when either the command includes the Recurse parameter or the path leads to the contents of a directory (stackoverflow.com/a/41700792)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.