Windows command prompt: decrementing loop
Posted by jpluimers on 2020/12/30
I needed a decrementing loop on the Windows command prompt, but that seems very hard from batch files without programming your own kind of while loop:
- [WayBack] Loops/For – Rosetta Code: Batch file
- [WayBack] windows – Batch script loop – Stack Overflow
PowerShell to the rescue to loop back from and including 463
down to and including 290
:
PowerShell -Command "for ($i=463; $i -ge 290; $i--) { Write-Host "Value " $i}"
This outputs:
Value 463 Value 462 ... Value 291 Value 290
In a similar way, you can execute a cmd command, but then you need to be careful on how to pass parameters: the \"
is important to you can have quotes within quoted strings..
PowerShell -Command "for ($i=463; $i -ge 290; $i--) { & echo \"Value $i\"}"
gives this:
Value 463 Value 462 ... Value 291 Value 290
But
PowerShell -Command "for ($i=463; $i -ge 290; $i--) { & echo Value $i}"
gives this:
Value 463 Value 462 ... Value 291 Value 290
More details are in:
- [WayBack] powershell – How to call a batch file with parameters from a command prompt – Stack Overflow (thanks Bill_Stewart)
- [WayBack] How to pass parameters to a batch file from Powershell – Stack Overflow (thanks lotpings!)
Practical
In my case, I needed to execute a batch file cm
with some parameters, so this had to be done through cmd /c cm parameters
, where the first bit needs to be separate from the last bits:
PowerShell -Command "for ($i=463; $i -ge 290; $i--) { & cmd \"/c cm log cs:$i\"}"
If you want to pause inbetween the the iterations:
PowerShell -Command "for ($i=463; $i -ge 290; $i--) { & cmd \"/c cm log cs:$i\" ; pause }"
If you want specialised output, remember to:
- escape all double quotes like the
\"
above - use semicolons
;
between statements - use
Write-Host
for output (as it is faster than shelling out toecho
) - use back-ticks for special characters, for instance
`r`n
forcarriage return
(CR
) followed bynewline/line feed
(LF
) - remember what
Write-Host
will automatically insert a newline, so you only need the`r
to make aCR
/LF
pair - redirect output at the end (but remember that a standard redirect only handles
stdout
, notstderr
)
PowerShell -Command "for ($i=463; $i -ge 290; $i--) { Write-Host \"`r`n### cs:$i`r`n`r`n``````text`r\" ; & cmd \"/c cm log cs:$i\" ; Write-Host \"```````r\" }" > commits.md
This will get output items like this (apart from a file commits.md
):
The specified changeset cs:443 does not exist.
plus a content of commits.md that has the output of each cm command output surrounded with pairs of these:
### cs:293 ```text cm output ``` ### cs:292 ```text cm output ```
Related
- No need for [WayBack]
Start-Process
and the-Wait
or-NoNewWindow
(but if you ever useStart-Process
, these two parameters are great: [WayBack] windows – Wait for batch file to finish process in Powershell before executing other commands? – Stack Overflow). - [WayBack] PowerShell Scripting: For Loops
- [WayBack] PowerTip: New Lines with PowerShell – Hey, Scripting Guy! Blog
–jeroen
Peter Wright said
Oh, so much easier to use Powershell than cmd’s equivalent:
FOR /L %%v IN (463,-1,290) DO ECHO Value: %%v