10

I am having problems with passing arguments to a batch function with nested double quotes.

Here is an example of a batch file:

@SET path_with_space="c:\test\filenamewith space.txt"
@CALL :FUNCTION blaat1, "blaat2 %path_with_space%"
@GOTO :EOF

:FUNCTION
@echo off
echo arg 1: %~1
echo arg 2: %~2
echo arg 3: %~3
GOTO :EOF

The output is:

arg 1: blaat1
arg 2: blaat2 "c:\test\filenamewith
arg 3: space.txt""

What should I do to make arg 2: blaat2 "c:\test\filenamewith space.txt"? Note that I cannot adjust the function or change the %path_with_space%. I can only control what is passed to the function.

Palec
  • 12,743
  • 8
  • 69
  • 138
Davor Josipovic
  • 5,296
  • 1
  • 39
  • 57

5 Answers5

13

Like dbenham said, it's seems impossible to escape a space in a parameter without quotes.
But it could be possible if you know how the receiver function gets the parameters.
Then you could tranfer the parameter via an escaped delayed variable, the variable will be expanded not in the call, it will be expanded just in the function.
And it's necessary that the parameters will be assigned in the function to variables, but this could be the case in a good and readable code.

setlocal EnableDelayedExpansion 
set path_with_space="c:\test\filenamewith space.txt"
@CALL :FUNCTION blaat1, "blaat2 ^!path_with_space^!"
GOTO :EOF

:FUNCTION
@echo off
echo arg 1: %~1
echo arg 2: %~2
echo arg 3: %~3
GOTO :EOF 

The output is:

arg 1: blaat1
arg 2: blaat2 "c:\test\filenamewith space.txt"
arg 3:

EDIT: Soltution with batch injection

This works even when delayed expansion should be always disabled.
But then you need to now how the parameters are expanded in the function.

@echo off
set path_with_space="c:\test\filenamewith space.txt"
CALL :FUNCTION 1 2 ""^^"&call:inject:""
exit/b

:inject
set arg1=blaat1
set arg2=blaat2 %path_with_space%
set arg3=none
exit /b

:FUNCTION
@echo off
set "arg1=%~1"
set "arg2=%~2"
set "arg3=%~3"
echo arg 1: %arg1%
echo arg 2: %arg2%
echo arg 3: %arg3%
GOTO :EOF
jeb
  • 78,592
  • 17
  • 171
  • 225
  • Wow, nice jeb! Tried escaping the `%`, but forgot about `!`. It makes sense now. Thanks! – Davor Josipovic Sep 23 '12 at 17:30
  • +1 - I thought of that solution, but I thought it wasn't acceptable because it requires delayed expansion to be enabled, a potential change for the function. – dbenham Sep 24 '12 at 00:55
  • @dbenham - I thought also of the problem of the delayed expansion, but you could also solve it with _batch injection_ – jeb Sep 24 '12 at 07:42
  • @jeb - Wow. I don't understand that batch injection at all, but I'm playing around with it. It's very strange. – James K Sep 24 '12 at 13:34
  • 2
    my turn - WOW. It took me a while to figure out how your batch injection works. The last quote isn't needed, but it does make the quotes balanced. Very interesting how the colon ends the label in the CALL, and everything after is effectively a comment up until any token delimiter. That is new for me. – dbenham Sep 24 '12 at 14:07
  • @dbenham - Some observations about labels are at [Dostips:Rules for label names vs GOTO and CALL](http://www.dostips.com/forum/viewtopic.php?f=3&t=3803) – jeb Sep 25 '12 at 12:04
2

I don't believe it is possible.

It is not possible to escape a space such that it is not interpreted as a parameter delimiter. The only way to include a space in a parameter is to enclose it in quotes. You require some space to be quoted and some not, so it is impossible.

dbenham
  • 127,446
  • 28
  • 251
  • 390
1

I found this but all i could do was move the issue around to different areas.

Working with Quotes

@SET 

path_with_space="c:\test\filenamewith space.txt"

:: Remove quotes
@SET _string=###%path_with_space%###
@SET _string=%_string:"###=%
@SET _string=%_string:###"=%
@SET _string=%_string:###=%

@echo %_string%

@CALL :FUNCTION blaat1, "blaat2 %_string%"
@GOTO :EOF

:FUNCTION
@echo off
@echo arg 1: %~1
@echo arg 2: %~2
@echo arg 3: %~3

:EOF


pause
glh
  • 4,900
  • 3
  • 23
  • 40
1

@jeb +1

@davor

why don't use simply double-double quotes

@SET path_with_space=""c:\test\filenamewith space.txt""
@CALL :FUNCTION blaat1, "blaat2 %path_with_space%", blaat3
@GOTO :EOF

:FUNCTION
@echo off
echo arg 1: %~1
::--------------------
set arg2=%~2
set arg2=%arg2:""="%
::-------------------
echo arg 2: %arg2%
echo arg 3: %~3
GOTO :EOF 

The output is:

arg 1: blaat1
arg 2: blaat2 "c:\test\filenamewith space.txt"
arg 3: blaat3
walid2mi
  • 2,704
  • 15
  • 15
  • This would work too, but ... The precondition of the OP was _Note that I cannot adjust the function_ – jeb Sep 24 '12 at 10:45
0

IF YOU DON'T WANT TO USE DELAYED EXPANSION (you need to edit FUNCTION to acomplish this!):

I suggest you to remove quotes before passing the arguments to FUNCTION (Note %path_with_space:"=%" vs %path_with_space%" in your original example) then you can put them back with replacing your path with quoted verion (%%_arg_2:%path_with_space:"=%=%path_with_space%%%):

@SET path_with_space="c:\test\filenamewith space.txt"
@CALL :FUNCTION blaat1, "blaat2 %path_with_space:"=%"
@GOTO :EOF

:FUNCTION
@echo off
echo arg 1: %~1
set _arg_2=%~2
call echo arg 2: %%_arg_2:%path_with_space:"=%=%path_with_space%%%
echo arg 3: %~3
GOTO :EOF

Output is:

arg 1: blaat1
arg 2: blaat2 "c:\test\filenamewith space.txt"
arg 3:

If other arguments also contain paths surrounded in quotes, you can follow the same pattern for all of them