Long commands in Windows batch files can be split to multiple lines by using the ^
as mentioned in Long commands split over multiple lines in Windows Vista batch (.bat) file.
However, if the caret is inside a double quoted string, it won't work. For example:
echo "A very long line I want to ^
split into two lines"
This will print "A very long line I want to ^
and tell me split
is an unknown command.
Is there a way to get around this?
How can you you insert a newline from your batch file output? You can insert an invisible ascii chr(255) on a separate line which will force a blank new line. Hold down the [alt] key and press 255 on the keypad.
Use double percent signs ( %% ) to carry out the for command within a batch file. Variables are case sensitive, and they must be represented with an alphabetical value such as %a, %b, or %c. ( <set> ) Required. Specifies one or more files, directories, or text strings, or a range of values on which to run the command.
The Windows command prompt (cmd.exe) allows the ^ (Shift + 6) character to be used to indicate line continuation. It can be used both from the normal command prompt (which will actually prompt the user for more input if used) and within a batch file.
[ == ] (Double Equals) The "IF" command uses this to test if two strings are equal: IF "%1" == "" GOTO HELP. means that if the first parameter on the command line after the batch file name is equal to nothing, that is, if a first parameter is not given, the batch file is to go to the HELP label.
I see three possible workarounds.
1) Building the line combining multiple for-parameters.
@echo off
SETLOCAL EnableDelayedExpansion
set "line="
for %%a in ("line1"
"line2"
"line3"
"line4"
) do set line=!line!%%~a
echo !line!
Drawback: It drops lines, when there is a ?
or *
in the text.
2) Leaving the "quote" at the end of each line
@echo on
SETLOCAL EnableDelayedExpansion
set "line=line1 & x#"^
"line2 & a#"^
"line3 & b #"^
"line4 & c "
set "line=!line:#" "=!"
echo !line!
The first space in each line is important, because the caret works as multiline character but it also escapes the first character, so also a quote would be escaped.
So I replace the unnessary #" " after building the line.
EDIT Added: 3) Disappearing quotes
setlocal EnableDelayedExpansion
echo "A very long line I want to !="!^
split into two lines"
In my opinion this is the best way, it works as the parser first see the quotes and therefore the last caret will work, as it seems to be outside of the quotes.
But this !="!
expression will expand the variable named ="
, but such a variable name can't exists (an equal sign can't occur as first character) so it expands to nothing.
You can also create safe expressions, they will always escape out of quotes, independent if there is a quote or not in the line.!="^"!
echo This multiline works !="^"!^
as expected
echo "This multiline works !="^"!^
too"
If you want avoid delayed expansion, you could also use a -FOR-Loop like
for %%^" in ("") do (
echo "This multiline works %%~"^
too"
)
The most straight forward answer is to escape the quotes. They will be printed, but they will not functionally quote the contents as far as CMD.EXE is concerned.
@echo off
echo ^"A very long line I want to ^
split into two lines^"
Any special characters that appear in the line must also be escaped since they are no longer functionally quoted.
@echo off
echo ^"A very long line I want to ^
split into two lines ^
that also contains special characters ^^ ^& ^| ^> ^< ^"
As jeb said, the line continuation escapes the first character of the next line. So if the first character of the next line happens to be a special character, it should not be escaped a second time. The code below will successfully escape the &
while it also introduces a new line.
@echo off
echo ^"A very long line I want to ^
split into two lines ^
that also contains special characters ^^ ^
& ^| ^> ^< ^"
I came up with my own method for this today, and I've never seen it suggested anywhere so I thought I'd post it here. Certainly, it's not elegant in an objective sense. I would say it has it's own unique kind of ugly and some limitations, but I find it far more "ergonomic" when compared to the alternatives.
Specifically, this method has the unique characteristic of not needing to escape anything, while still performing typical variable substitution. This enables me to to take some string that looks exactly how I want it, spread it across multiple lines, and add a prefix to each line without changing anything else in the string. Thus, there's no trial-and-error needed to figure out how special characters and escape characters might interact. Overall, I think it reduces the cognitive load needed to deterministically produce a complicated string variable over multiple lines, which is good for me because I don't want to have to think hard and get frustrated with incidental complexity like the nuances of the windows command interpreter. Also, a similar technique can be used on linux bash, making it somewhat portable.
Note: I've not thoroughly tested it, it might not work for some use cases, I don't know. However, the example has a fair number of seemingly troublesome characters an it works, so it seems somewhat robust.
set IMAGE_NAME=android-arm64
set CMD=docker run --rm
set CMD=%CMD% --platform=linux
set CMD=%CMD% -v %CD%:/work
set CMD=%CMD% dockcross/%IMAGE_NAME%
set CMD=%CMD% /bin/sh -c
set CMD=%CMD% "mkdir build-%IMAGE_NAME% &&
set CMD=%CMD% cd build-%IMAGE_NAME% &&
set CMD=%CMD% cmake .. &&
set CMD=%CMD% cmake --build ."
echo %CMD%
In my case, it's a command, so I can run it with:
%CMD%
I'd be open to any feedback or suggestions about this method. Perhaps it can even be improved.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With