Owen
Owen

Reputation: 7784

How to include pipe character in an argument to a batch file from a bash script?

I have a shell script that I want to execute this line:

qtvars.bat vsstart "qt.sln" /BUILD "Debug|Win32"

This works fine (though I had to modify qtvars.bat, but that's beside the point). The problem is that I want the command to execute to be in a variable: EDIT: This doesn't work either, if I type it into bash. Previously I was typing it into cmd.exe, which hardly made for a fair comparison.

command="qtvars.bat"
args="vsstart"

$command $args "qt.sln" /BUILD "Debug|Win32"

Now it chokes on the pipe! I get this message:

'Win32' is not recognized as an internal or external command,
operable program or batch file.

I've tried a bunch of forms of escaping the quotes and/or pipe, all to no avail. Interestingly, it works when it's an executable rather than a batch file, e.g.:

command="devenv.exe"
args=""

$command $args "qt.sln" /BUILD "Debug|Win32"

Thanks for any ideas.

Upvotes: 8

Views: 13913

Answers (6)

dirkgently
dirkgently

Reputation: 111120

Interesting! What does escaping the | do?

Do these work?

echo "Debug|Win32"
echo "qt.sln" /BUILD 'Debug|Win32'

Upvotes: 0

Valiante
Valiante

Reputation: 182

I know you "escape" the pipe character in a batch file with the ^ character, so...

echo ^| Some text here ^|

Would display...

| Some text here |

I don't know whether that would help you in this instance? Maybe try prepending each pipe character with a ^ and see what happens? :-)

Upvotes: 9

DennisVM-D2i
DennisVM-D2i

Reputation: 490

I'd consider going the easy route, and passing a placeholder-token instead - "$P", and then replace it within the CMD/Batch file; e.g. using the 'UnxUtils' SEd command to do the replacement:

For /F "usebackq delims=" %%r in (`Echo %Cmd% ^| sed -e "s/$P/|/g"`) do @Set Cmd2=%%r

REM  Now run the command, with the proper pipe symbol in place

%Cmd2%

So having passed the command arg/CMD script args - "git status $P wc -l".

Upvotes: 0

John Beavers
John Beavers

Reputation: 11

Escaping a piping character in the Windows scripting language is done with a caret (^). I just had to do this the other day. I know this is old, but I thought I would post what I found in case others ran across this, like I did.

Upvotes: 1

vladr
vladr

Reputation: 66661

This is a classic case of double-escaping, where both bash and CMD.EXE need to be instructed to ignore the special | (pipe) character.

Try the following:

$command $args "qt.sln" /BUILD '"Debug|Win32"'

This will be the equivalent of you typing, at a CMD.EXE prompt:

qtvars.bat vsstart qt.sln /BUILD "Debug|Win32"

Using the above, you are essentially forcing the passing of the double-quotes on to CMD.EXE (instead of bash eating them away.) The outermost single quotes instruct bash not to interpret or touch in any way what's inside them; the inner double-quotes instruct CMD.EXE to ignore any special characters (the pipe in this case) within.

Alternatively, you can also try:

$command $args "qt.sln" /BUILD 'Debug\|Win32'

This should be the equivalent of you typing, at a CMD.EXE prompt:

qtvars.bat vsstart qt.sln /BUILD Debug\|Win32

Note the use of single quotes (!), which ensure that bash will not interpret the \ (and, instead, will pass it as-is to CMD.EXE.)

Upvotes: 3

rdesgroppes
rdesgroppes

Reputation: 1107

Here's another solution (workaround?) I've found:

first, ensure an environment variable defines the pipe character, for example:
set PIPE="|"

later, run the command specifying the above defined environment variable name:
"c:\(...)\devenv.com" foo.sln /build Debug%PIPE%Win32

That does the job even if there are multiple wrappers between the caller and the callee. I'm now using it with a very long chain of wrappers: Python/Linux -> VirtualBox guest's executeProcess -> Cmd/Windows -> devenv.com

(cross posted to: How to pass a quoted pipe character to cmd.exe?)

Upvotes: 1

Related Questions