Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to split double quoted line into multiple lines in Windows batch file?

Tags:

batch-file

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?

like image 785
Wang Dingwei Avatar asked Jan 10 '11 03:01

Wang Dingwei


People also ask

How do I create a line break in batch file?

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.

What is %% in a batch file?

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.

How can I write a long command over multiple lines in either the command prompt window or a batch file?

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.

What is == in batch?

[ == ] (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.


3 Answers

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"
)
like image 168
jeb Avatar answered Oct 13 '22 04:10

jeb


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 ^^ ^
& ^| ^> ^< ^"
like image 12
dbenham Avatar answered Oct 13 '22 06:10

dbenham


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.

like image 4
solvingJ Avatar answered Oct 13 '22 06:10

solvingJ