can’t call func with "/?" as param

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
Sponge Belly
Posts: 234
Joined: 01 Oct 2012 13:32
Location: Ireland
Contact:

can’t call func with "/?" as param

#1 Post by Sponge Belly » 18 Apr 2013 16:52

Hi Everyone!

Apologies if this topic has been discussed before, but I recently tried to write an error subroutine. I invoked it like this:

Code: Select all

call :error "file "%~1" not found " || goto end


This worked just fine… until I passed "/?" as a filename. The program died, displaying the help info for call. :?:

Turns out call splits its parameters into tokens separated by the usual suspects (space, comma, semi-colon, and equals). Double quotes have no special meaning, as far as call is concerned. For example:

Code: Select all

call :mysub "apple banana cherry"


will store <"apple> in %1, <banana> in %2, and <cherry"> in %3. :twisted:

I suppose I could store the error message in a variable and pass the variable name as a parameter to the subroutine which would use delayed expansion to expand it, but that would be an awful kludge, imho.

So… is there a simpler solution? One that can cope with anything thrown at it, even parameters such as "/?"

TIA! :-)

- SB

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: can’t call func with "/?" as param

#2 Post by dbenham » 18 Apr 2013 18:40

Sponge Belly wrote:Turns out call splits its parameters into tokens separated by the usual suspects (space, comma, semi-colon, and equals). Double quotes have no special meaning, as far as call is concerned.

For example:

Code: Select all

call :mysub "apple banana cherry"
will store <"apple> in %1, <banana> in %2, and <cherry"> in %3. :twisted:

You fooled yourself. The parameter parser ignores quoted token delimiters. The code above stores "apple banana cherry" in %1

The reason your /? filename did not work is because you have quotes within quotes, so the /? is no longer quoted.

Simply remove the inner quotes and you will get the entire string in %1:

Code: Select all

call :error "file %~1 not found " || goto end

But that might cause problems if your error routine uses ECHO %~1 and you get a file name containing &

Quotes are a state machine. If quoting is on, then the next quote will turn it off. You can escape a quote as ^" to prevent it from turning the quote state ON. Unfortunately, once the quote state is ON, it is impossible to escape the next quote to prevent it from turning the quote state OFF again.


Dave Benham

Sponge Belly
Posts: 234
Joined: 01 Oct 2012 13:32
Location: Ireland
Contact:

Re: can’t call func with "/?" as param

#3 Post by Sponge Belly » 19 Apr 2013 10:22

Hi Dave!

Well, colour me embarrassed. :oops:

That‘ll teach me to test my fruity hypotheses more thoroughly before opening my enormous gob.

Anyways, I took on board what you said and came up with the following:

Code: Select all

@echo off & setlocal enableextensions
(set file="%~1")

echo(delayed expansion is off
call :error "file !file! not found"

setlocal enabledelayedexpansion
echo(delayed expansion is on
call :error "file ^!file^! not found"
endlocal

endlocal & goto :EOF

:error
setlocal enabledelayedexpansion
>&2 echo(%~1
endlocal & exit /b 1


Works with input such as "/?", "*.tmp", and "this&that.txt". A faint whiff of kludge still lingers over the code, but I can live with it… for now.

Thanks for your help.

- SB

Post Reply