Why does this batch file fail on a "REM" line?

7,340

Solution 1

The error-msg refers to the commented out second line

This is due to the very complex parsing that is used by cmd to process scripts.

In short the parser processes % before pretty much everything else (phase 1) and throws an error as some of the %s need to be doubled as %% when used in a batch file.

So in a batch file:

for %%F in (*.pdf) do ren "%%~F" "%%~nF OdB%%~xF"

is a valid command and:

REM for %a in (*.txt) do ren "%~a" "%~na version 1%~xa"

is a broken command (the %a should be %%a, etc).

Note that:

REM for %a in (*.txt) do ren "%~a" "%~na version 1%~xa"

is a valid command when run from the command line as then the % does not need to be doubled.

REM would be processed in phase 2 of the parser, but it never gets there as the % processing in phase 1 has already generated an error and terminated the parsing.

For all the gory details of the cmd parser please read parsing - How does the Windows Command Interpreter (CMD.EXE) parse scripts? - Stack Overflow

Solution 2

It doesn't work because even though it is "remarked" it is evaluated for substitutions, and then apparently discarded.

For "batch" your second line is incorrect and should read

REM Rework 2020-12-16
REM for %%a in (*.txt) do ren "%%~a" "%%~na version 1%%~xa"
for %%F in (*.pdf) do ren "%%~F" "%%~nF OdB%%~xF"

The corrections being that in batch programming expansions need to have %% rather than a single %.

Solution 3

To add to the existing answers, although REM is used for comments, it is important to understand that it is actually a command that does nothing, not a comment. This is different from a Unix shell, where you have real comments and can add arbitrary text after a # character.

Not only the substitutes are evaluated for the REM command, also file redirects. So beware that the following line will delete the content of the file, because the REM command produces no output, but the empty output will be redirected to the file

REM some_command > important_file

Edit

As a comment pointed out, this is no longer true for modern Windows versions. According to https://stackoverflow.com/a/4095133/10765659 there is now special handling of REM so that redirections are not executed, but this special handling occurs too late to make REM a true comment, as the substitutes are still evaluated.

Share:
7,340

Related videos on Youtube

gkln
Author by

gkln

Updated on September 18, 2022

Comments

  • gkln
    gkln over 1 year

    I refer to question Add text to end of filename (but before extension) using batch file as I have the same problem. Using Windows 7 32-bit Enterprise (I know, I know ...) with all updates I wrote a tiny batch file pdfrename.bat with only three lines:

    1. a comment, starting with REM and no "hidden" continuation sign more to the right of the line

    2. the proposed command, copy-pasted from the source as provided by @Karan, commented out with REM

    3. the adopted command for batch (doubling the %):

      REM Rework 2020-12-16
      REM for %a in (*.txt) do ren "%~a" "%~na version 1%~xa"
      for %%F in (*.pdf) do ren "%%~F" "%%~nF OdB%%~xF"
      

    Running the command (3.) from the command-prompt,

    for %F in (*.pdf) do ren "%~F" "%~nF OdB%~xF"
    

    works fine.

    But executing the whole batch-file pdfrename.bat from Windows explorer fails. Running the batch file from the command prompt pdfrename.bat produces an error message syntax error:

    Die folgende Verwendung des Pfadoperators zur Ersetzung eines Batchparameters
    ist ungültig: %~na version 1%~xa"
    [...]
    

    You need not to understand German. The important point is that the error message refers to the commented out second line (2.), not to the third line!

    I tried to retype REM, inserted a tabulator after REM, inserted a second REM after the first (REM REM ....), inserted a third line after the second one with the same content and deleted the second line afterwards - nothing changed: the batch file terminates at the commented out second line with a syntax error. As soon as the incriminated second line is eliminated from the batch, the batch works fine.

    I searched for "REM is ignored", but no luck, so I post the matter here. I never heard about or experienced before that the command processor tries at least to analyze a commented out line - and in the case that there is something wrong with the code after the comment-sign that it terminates the batch script.

    • Christoffer Hammarström
      Christoffer Hammarström over 3 years
    • Olivier Dulac
      Olivier Dulac over 3 years
      a workaround: if you wanted to provide an exemple: change this to say something like: REM to do the same in a command prompt, divide the number of variable calls, for ex: %%f , by two. ie, only have 1 percent sign instead of 2
  • Mokubai
    Mokubai over 3 years
    Technically the for %a in (*.txt) do ren "%~a" "%~na version 1%~xa" is correct so long as it's not in a batch file itself. :)
  • gkln
    gkln over 3 years
    @DavidPostill with other words "works as designed" - but not as described in tutorials. Even herer docs.microsoft.com/en-us/windows-server/administration/…
  • Kamil Maciorowski
    Kamil Maciorowski over 3 years
    Have you tested the alleged redirection issue? How exactly? In what OS? My tests (in Win 7 so far) don't confirm the issue, the content of important_file survives. This other answer states REM is special in phase 2 and "treated dramatically different". It seems what I observed confirms the other answer, not yours.
  • Euro Micelli
    Euro Micelli over 3 years
    Another way to look at it: don’t think of REM as a comment, but as an internal command that does nothing with its arguments.
  • Ruslan
    Ruslan over 3 years
    @EuroMicelli it's quite similar to the true or : command in Unixes, but working only inside batch scripts.
  • nerkn
    nerkn over 3 years
    There are also labels in batch scripts, which are written as :: and are also often used as comments: <stackoverflow.com/questions/16632524/…>
  • RalfFriedl
    RalfFriedl over 3 years
    @KamilMaciorowski I didn't test this recently. A colleague had this problem in the time of early Windows, probably around or before Windows 95, and I avoided that ever since. I'm glad to hear that it has been fixed.
  • DavidPostill
    DavidPostill over 3 years
    @gkln Do you need more help? If this answered your question, please don't forget to accept the answer by clicking the accept button (the tick ✓ button). Also see Why is voting important?
  • Andrew Ray
    Andrew Ray over 3 years
    Batch labels actually start with only a single :. A label written as ::label actually defines a label called :label. It is safe to use this as a pseudo-comment, however, because GOTO : has special handling for things like GOTO :EOF, so it's impossible to accidentally jump to a label that starts with a colon.
  • karan punjabi
    karan punjabi over 3 years
    Wow, this just blew my mind. The CMD parser processes text before acknowledging it's just a comment. Just... WOW.
  • Scott - Слава Україні
    Scott - Слава Україні over 3 years
    I was going to upvote this post for actually answering the question better than any of the other answers. But then I saw that, after seeing a comment pointing out an error in your post, you acknowledged it in another comment but you didn't edit the answer.
  • gkln
    gkln over 3 years
    @Massimo Thanks!