Powershell command in batch file: Remove all lines from text file except lines with “foo” and “bar”

batchcommand linepowershellwindows

I have a text file with these 3 lines:

This line contains foo.
This line contains bar.
This line has neither.

I can run the below command in a ".bat" file (next to the above ".txt" file) and it removes all lines in the text file except lines containing "foo":

Powershell.exe -Command "gci *.txt | foreach { (cat $_.FullName | ? { $_ -like '*foo*' }) | set-content $_.FullName}"

Running that has the intended effect, leaving only this line in the text file:

This line contains foo.

Now the problem: What if I want to keep lines that have "foo" and "bar" in the line?

I must have tried probably 40 or 50 different combinations up to now, putting a pipe character: *foo*|*bar*, taking out the asterisks foo|bar, putting asterisks only at the start and end: *foo|bar*, using a comma, not using a comma, using a semi-colon, not using a semi-colon, duplicating the -like command with and without $_ and many other ways.

Nothing works – on every attempt up to now, I just end up with the text file looking the same, with the original three lines containing foo (line 1), bar (line 2) and neither (line 3).

To make sure I'm not editing the command and making an error, I am periodically removing my edits and running the command again to just take out lines without "foo" on the line and it works, or I just paste the command again, test it again, then begin trying to edit it to include "bar", to no avail.

I have already asked this question recently, but I guess my wording of the title wasn't clear. Someone has tried to answer it, but every answer they have provided hasn't worked, at least when I am putting the command in a batch file and running it next to the text file, maybe it's working for them, using a different method to the one I am, I don't know.

Please note that I am using a powershell command in a batch file! I'm not typing in a console or using ps1 scripts.
I don't need to do any of that, because the very first command I have mentioned above does work to remove all lines with "foo".

Obviously since that does work, the command can be used as a foundation to add to, so it can handle "foo" and "bar" in the one command.

Unless of course this is 100% impossible – which after about 4 days now of trying 40 or 50 different variations on the command – is what I am starting to suspect!

Please, if anyone answers this, post a batch file command just like I have above. Please don't tell me to swap over to using ps1 scripts or give answers that are explaining what to type into a console window.

The command I have posted above simply needs some sort of amendment so "bar" can be added to "foo", so it handles more than one text string.

The reason this is so difficult seems to be because if you run a command to take out all lines except ones with "foo" then you've already taken out lines with "bar". I suspect this is why no one has come up with a working solution yet and maybe there just isn't one.

Thanks in advance to anyone that has a working answer. Normally these things are answered here really fast, or I just keep trying different ways and I get it to work – but not this time, this is a real tough one for some reason.

Best Answer

Just use two separate conditions joined with OR:

cat $_.FullName | ? { $_ -like '*foo*' -or $_ -like '*bar*' }

Parentheses can be used to add clarity, but they're optional:

{ ($_ -like '*foo*') -or ($_ -like '*bar*') }

post a batch file command just like I have above. Please don't tell me to swap over to using ps1 scripts or give answers that are explaining what to type into a console window.

Those are literally the same thing. It doesn't matter how you invoke a PowerShell script – whether it's stored in a file or passed through the command line or input by keyboard, it's still a PowerShell script and it follows the same syntax rules.

Related Question