4

When I run the following batch script:

@echo off
REM %~ will strip surrounding quotes if any

echo HERE

I get the following error:

C:\>test.cmd
The following usage of the path operator in batch-parameter
substitution is invalid: %~ will strip surrounding quotes if any

For valid formats type CALL /? or FOR /?

Same effect if REM is changed to ::.

Seems like the parser is ignoring the comment indicator and parsing the %~. If I put a space between the % and ~ then it works fine.

Windows 7 Enterprise (have not checked any other versions).

Seems like a bug to me, but am I missing something?

michael_heath
  • 5,262
  • 2
  • 12
  • 22
codesniffer
  • 1,033
  • 9
  • 22
  • 3
    I think that happens in an early parsing phase, for details see [how-does-the-windows-command-interpreter-cmd-exe-parse-scripts](https://stackoverflow.com/questions/4094699/how-does-the-windows-command-interpreter-cmd-exe-parse-scripts) –  Nov 21 '18 at 00:59

2 Answers2

3

The %-expansion, hence expanding normal environment variables (like %VAR%) as well as command line arguments (like %0), is the very first step after having read a line, therefore it happens even before the rem command is recognised. Thus you need to avoid the %~ (by writing rem % + ~ ..., for instance).

Given that the command extensions are enabled, which is the default anyway, %~ is recognised as invalid argument syntax (the ~ is expected to be followed by a decimal digit denoting the argument position or by a valid modifier like f, d, p, n, x, etc.; see Command Line arguments (Parameters)) and results in a fatal error, meaning that an error message is thrown and batch file processing is aborted (the %ErrorLevel% is not set though).

The same effect comes up when you try to do sub-string substitution but specifying an empty search string (like %VAR:=replace% or %VAR:*=replace%, given that VAR is defined), also with command extensions enabled.

See also this thread: How does the Windows Command Interpreter (CMD.EXE) parse scripts?

aschipfl
  • 33,626
  • 12
  • 54
  • 99
3

I think it is clearly covered in quite a few docs that cmd will interpret the arguments before comments, see the example in @LotPings comment as well as @aschiphl's post. That being said, you can momentarily disableextensions and then turn it back on when needed. The below example shows how disabling it will allow you to use it in the REM comment and then enabled again after to show allow extensions:

@echo off
setlocal disableextensions
REM %~ will strip surrounding quotes if any"
endlocal
echo my batch file is %~0
Gerhard
  • 22,678
  • 7
  • 27
  • 43
  • 3
    Instead of `setlocal enableextensions` I would use `endlocal` to return to the former state (default) and to the former environment, thus having the same state as in the original code... – aschipfl Nov 21 '18 at 09:01
  • @aschipfl true yes, I think I just wanted to demonstrate enable and disable, but will change. – Gerhard Nov 21 '18 at 09:18
  • Thanks for the workaround idea! Considering the extra lines to work around this, I simply used a valid expression there: %~1. – codesniffer Nov 22 '18 at 01:27