0

I am running Powershell commands in a batch file to replace text.

This works, but it runs an instance of Powershell every time it replaces something:

:: Replace foo1 with bar1
start /wait /min Powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "Get-ChildItem '*.txt' | ForEach-Object {(Get-Content $_) -replace 'foo1', 'bar1' | Set-Content $_.FullName}"

:: Replace foo2 with bar2
start /wait /min Powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "Get-ChildItem '*.txt' | ForEach-Object {(Get-Content $_) -replace 'foo2', 'bar2' | Set-Content $_.FullName}"

:: Replace foo3 with bar3
start /wait /min Powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "Get-ChildItem '*.txt' | ForEach-Object {(Get-Content $_) -replace 'foo3', 'bar3' | Set-Content $_.FullName}"

Is there a way to chain the three commands by adding something like & ^ at the end of a line, part way through the 2nd command?

I want to keep each -replace command on a separate line because I have over 100 commands to chain together.

I have tried to do it this way and it doesn't work:

:: Replace foo1 with bar1
start /wait /min Powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "Get-ChildItem '*.txt' | ForEach-Object {(Get-Content $_) -replace 'foo1', 'bar1' | & ^

:: Replace foo2 with bar2
 | ForEach-Object {(Get-Content $_) -replace 'foo2', 'bar2' | & ^

:: Replace foo3 with bar3
 | ForEach-Object {(Get-Content $_) -replace 'foo3', 'bar3' | Set-Content $_.FullName}"

I have also tried the above without the & character.

I tried removing ForEach-Object {(Get-Content $_) from the middle and last lines, doesn't work.

Is it the :: comments causing a problem?

I thought since this is Powershell commands enclosed in double quotes, I'll try this way, where the back tick and semi-colon at the end of each line should tell Powershell to carry on the command and treat the next line as part of the same command:

:: Replace foo1 with bar1
start /wait /min Powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "Get-ChildItem '*.txt' | ForEach-Object {(Get-Content $_) -replace 'foo1', 'bar1';`

# Replace foo2 with bar2
 | ForEach-Object {(Get-Content $_) -replace 'foo2', 'bar2';`

# Replace foo3 with bar3
 | ForEach-Object {(Get-Content $_) -replace 'foo3', 'bar3' | Set-Content $_.FullName}"

(doesn't work)

I tried taking some of the Powershell commands out:

:: Replace foo1 with bar1
start /wait /min Powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "Get-ChildItem '*.txt' | ForEach-Object {(Get-Content $_) -replace 'foo1', 'bar1';`

# Replace foo2 with bar2
'foo2', 'bar2';`

# Replace foo3 with bar3
'foo3', 'bar3' | Set-Content $_.FullName}"

(Doesn't work).

I have tried taking out the comments altogether, doesn't work.

I have tried adding back -replace to the start of each line, doesn't work.

This doesn't work trying to put it on one line:

start /wait /min Powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "Get-ChildItem '*.txt' | ForEach-Object {(Get-Content $_) -replace 'foo1', 'bar1'; -replace 'foo2', 'bar2'; -replace 'foo3', 'bar3' | Set-Content $_.FullName}"

Putting a pipe instead of a semi-colon doesn't work either:

start /wait /min Powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "Get-ChildItem '*.txt' | ForEach-Object {(Get-Content $_) -replace 'foo1', 'bar1' | -replace 'foo2', 'bar2' | -replace 'foo3', 'bar3' | Set-Content $_.FullName}"

There are probably dozens of different combinations trying to get this to work, but I have no idea what the right way is and I'm out of ideas.

The commands aren't working when chained together with a ; like described in other answers.

Cheers.

1
  • 3
    Why not use powershell only? You are going about it the wrong way. Powershell can do everything batch can and more, so wrapping each command in batch is not only making things a lot harder on yourself, you run into problems like these. Just create one .ps1 file and put all your commands in there and run that from your batch file or directly from explorer. Instead of -Command ... you use -File file.ps1. You can then use PowerShell ISE to edit your ps1 which is even better than most text editors for batch files too. – LPChip May 4 at 6:45
2

You want to put many commands in a row and call it from a batch file?

Not only will your method not work because you can't put that many characters in one command in a batch file, but its also not possible to chain them that easily.

The obvious solution here is to either only use PowerShell or put all the commands in a .ps1 file and change your powershell command in your batch file to:

start /wait /min Powershell.exe -NoProfile -ExecutionPolicy Bypass -File MyFile.ps1

To edit your .ps1 file, use PowerShell ISE. This not only gives you syntax highlighting, you can very easily test what you are doing by running one command instead of the entire script and every variable you set in your script is retained after execution so you can test in the console live after your script has run to debug where things are not working correctly.

Every command you would run in your batch file can be run in PowerShell too. Even if logic etc. And PowerShell offers functions so you can write code that is much easier to read too.

4
  • Cheers, I know taking it away from a batch file and to a .ps1 script would make things easier but I have tried and never managed to get a ps1 script to run from a batch file. OK I will try it, but I gave up on that weeks ago, hence why it's all in a batch file. – bat_cmd May 4 at 6:59
  • 1
    " I have tried and never managed to get a ps1 script to run from a batch file. " Do it all in a PowerShell script! – Keith Miller May 4 at 7:27
  • Then Windows asks what to open it with, or might, I am trying to make it run anytime anywhere :p – bat_cmd May 4 at 8:08
  • From Windows 7 and up (which is basically every windows that is in use with the exception of maybe 0.01%?) everyone has Powershell, so your script will run. The powershell calling will work if powershell.exe is in the path environmental variable. To counteract, locate powershell in your windows folder and put its entire path in your .bat file and it will always work. – LPChip May 4 at 8:27
0

You can try one line with multiples .replace():
.replace('foo1','bar1').replace('foo2','bar2').replace('foo3','bar3')...

start "" /wait /min /wait Powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "Get-ChildItem '*.txt' | foreach {(Get-Content $_).replace('foo1','bar1').replace('foo2','bar2').replace('foo3','bar3')|Set-Content $_.FullName -force}"
0

A troll is down voting every question I ask (always on -1 and never any reason for it). Mods please check into who is doing that, thanks.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.