Forum Discussion

TaggAurel's avatar
TaggAurel
Copper Contributor
Apr 13, 2022
Solved

Batch file: filename with ampersand (&)

Hello,

 

I have a simple bat file named "test&.bat" with this content:

@echo off

echo This is test.bat
pause

When I use "Run as administrator" on the file, the pause command is not handled.

When I double-click on the file, it works.

When I rename the file as "test.bat", it works even with "Run as administrator".

 

Do you have any idea why the ampersand character causes troubles with "Run as administrator"?

  • TaggAurel 

     

    Taking a look behind the scenes with Process Monitor, the commands passed to the shell are formatted differently.

     

    The TL;DR reason it that it's got to do with the Windows Explorer shell and a difference in how the filename is parsed and provided in the call to cmd.exe.

     

    Initial observations from Process Monitor

    When the filename contains the ampersand, the following occurs:

     

    Normal user double-clickingExecutes
    Run as administratorDoes not execute

     

    So, the issue isn't the "pause" statement. The issue is the batch file doesn't actually run at all. cmd.exe is certainly called but the batch file within the new cmd.exe process fails to execute as it is interpreted as two separate commands.

     

    This is because there's a difference in parsing in the Windows Shell between "normal" and "as administrator" launch experience.

     

    The commands strings produced for each scenario were:

    Normal user double-clicking
    C:\Windows\system32\cmd.exe /c ""D:\Data\Temp\test&.bat" "
    Run as administrator
    "C:\Windows\System32\cmd.exe" /C "D:\Data\Temp\test&.bat"

     

    The character escaping and quoting issue

    As I already mentioned, the ampersand is a reserved character that denotes the separation of commands. This is better discussed in the following article which also outlines how it can be a dangerous practice to leave unchecked.

     

    Blaming the operating system for allowing people to create files with unusual characters in their names - The Old New Thing (microsoft.com)

     

    Even so, the issue isn't strictly the filename but rather that the parsing in the "run as administrator" version - through not properly escaping or quoting the arguments - is effectively producing two commands - not one - either side of the ampersand.

     

    Reproduction

    There are two easily-accessed methods for reproducing successful or erroneous outcomes:

     

    1. Via the Start | Run box;
    2. Via PowerShell's Start-Process commandlet.

    For example, you can reproduce the baseline "run as administrator" failure using Start-Process as follows:

     

    Start-Process -FilePath '"C:\Windows\System32\cmd.exe"' -ArgumentList @('/c', '"D:\Data\Temp\test&.bat"') -RedirectStandardError D:\Data\Temp\sp-out.txt

     

     

    The redirected standard error file contains the two errors (one per line) associated with interpreting the filename as two separate commands:

    'D:\Data\Temp\test' is not recognized as an internal or external command, operable program or batch file.
    '.bat' is not recognized as an internal or external command, operable program or batch file.

     

    Approaches to launching successfully

    Rename the file to not include the ampersand

    This doesn't need explaining as you're already aware of this.

     

    "Double" double quotes

    This is common in many programming an scripting languages but inaccessible from simple clicking on files in the shell (natively, at least - you could elect to create a properly-formatted shortcut.)

     

    For example, doubling the quotes for the file path argument would take this:

    "C:\Windows\System32\cmd.exe" /C "D:\Data\Temp\test&.bat"

    To this:

    "C:\Windows\System32\cmd.exe" /C ""D:\Data\Temp\test&.bat""

     

    Using Start-Process to demonstrate a successful launch using this method:

     

    Start-Process -FilePath '"C:\Windows\System32\cmd.exe"' -ArgumentList @('/c', '""D:\Data\Temp\test&.bat""') -RedirectStandardError D:\Data\Temp\sp-out.txt

     

     

    Properly escaping the ampersand

    For the command shell, the caret is the nominated escaping character and should be used where special characters are used within the filename.

     

    For example, escaping would take this:

    "C:\Windows\System32\cmd.exe" /C "D:\Data\Temp\test&.bat"

    To this:

    "C:\Windows\System32\cmd.exe" /C "D:\Data\Temp\test^&.bat"

     

    Using Start-Process to demonstrate a successful launch using this method:

     

    Start-Process -FilePath '"C:\Windows\System32\cmd.exe"' -ArgumentList @('/c', '"D:\Data\Temp\test^&.bat"') -RedirectStandardError D:\Data\Temp\sp-out.txt

     

     

    Summary

    Using the ampersand in a filename isn't a good idea. That said, the underlying cause of the issue you noted is that two different command lines are produced depending on whether your simply double-click on the batch file or run it "as an administrator".

     

    The former command line is properly quoted, allowing the command to run even with the ampersand, while the latter command line is neither properly formatted nor escaped, causing the associated cmd.exe process to be created but the command within that new process to fail execution.

     

    The best solution is not to use reserved characters for any given shell within filenames but if that can't be avoided, to ensure the batch file(s) are launched using the proper escaping or quoting so the file name/path is not treated as separate commands (which is the by-design and expected outcome.)

     

    Cheers,

    Lain

  • LainRobertson's avatar
    LainRobertson
    Silver Contributor

    TaggAurel 

     

    Yes, the ampersand has a very long history as a special character in the command prompt shell.

     

    From the bottom of the command prompt shell help itself, it states:

     

    The special characters that require quotes are:
    <space>
    &()[]{}^=;!'+,`~

     

    So, put simply, your example needs to use double quotes to look like this:

     

    @echo off
    
    REM This following line will NOT work!
    test&.bat
    
    REM This will work.
    "test&.bat"
    pause

     

    Cheers,

    Lain

    • TaggAurel's avatar
      TaggAurel
      Copper Contributor

      Thank youLainRobertson for your answer!

      But I still don't understand why the "right-click->Run as administrator" doesn't have the same behavior as double-click on file test&.bat.

      Anyway, I have a workaround.

      • LainRobertson's avatar
        LainRobertson
        Silver Contributor

        TaggAurel 

         

        Taking a look behind the scenes with Process Monitor, the commands passed to the shell are formatted differently.

         

        The TL;DR reason it that it's got to do with the Windows Explorer shell and a difference in how the filename is parsed and provided in the call to cmd.exe.

         

        Initial observations from Process Monitor

        When the filename contains the ampersand, the following occurs:

         

        Normal user double-clickingExecutes
        Run as administratorDoes not execute

         

        So, the issue isn't the "pause" statement. The issue is the batch file doesn't actually run at all. cmd.exe is certainly called but the batch file within the new cmd.exe process fails to execute as it is interpreted as two separate commands.

         

        This is because there's a difference in parsing in the Windows Shell between "normal" and "as administrator" launch experience.

         

        The commands strings produced for each scenario were:

        Normal user double-clicking
        C:\Windows\system32\cmd.exe /c ""D:\Data\Temp\test&.bat" "
        Run as administrator
        "C:\Windows\System32\cmd.exe" /C "D:\Data\Temp\test&.bat"

         

        The character escaping and quoting issue

        As I already mentioned, the ampersand is a reserved character that denotes the separation of commands. This is better discussed in the following article which also outlines how it can be a dangerous practice to leave unchecked.

         

        Blaming the operating system for allowing people to create files with unusual characters in their names - The Old New Thing (microsoft.com)

         

        Even so, the issue isn't strictly the filename but rather that the parsing in the "run as administrator" version - through not properly escaping or quoting the arguments - is effectively producing two commands - not one - either side of the ampersand.

         

        Reproduction

        There are two easily-accessed methods for reproducing successful or erroneous outcomes:

         

        1. Via the Start | Run box;
        2. Via PowerShell's Start-Process commandlet.

        For example, you can reproduce the baseline "run as administrator" failure using Start-Process as follows:

         

        Start-Process -FilePath '"C:\Windows\System32\cmd.exe"' -ArgumentList @('/c', '"D:\Data\Temp\test&.bat"') -RedirectStandardError D:\Data\Temp\sp-out.txt

         

         

        The redirected standard error file contains the two errors (one per line) associated with interpreting the filename as two separate commands:

        'D:\Data\Temp\test' is not recognized as an internal or external command, operable program or batch file.
        '.bat' is not recognized as an internal or external command, operable program or batch file.

         

        Approaches to launching successfully

        Rename the file to not include the ampersand

        This doesn't need explaining as you're already aware of this.

         

        "Double" double quotes

        This is common in many programming an scripting languages but inaccessible from simple clicking on files in the shell (natively, at least - you could elect to create a properly-formatted shortcut.)

         

        For example, doubling the quotes for the file path argument would take this:

        "C:\Windows\System32\cmd.exe" /C "D:\Data\Temp\test&.bat"

        To this:

        "C:\Windows\System32\cmd.exe" /C ""D:\Data\Temp\test&.bat""

         

        Using Start-Process to demonstrate a successful launch using this method:

         

        Start-Process -FilePath '"C:\Windows\System32\cmd.exe"' -ArgumentList @('/c', '""D:\Data\Temp\test&.bat""') -RedirectStandardError D:\Data\Temp\sp-out.txt

         

         

        Properly escaping the ampersand

        For the command shell, the caret is the nominated escaping character and should be used where special characters are used within the filename.

         

        For example, escaping would take this:

        "C:\Windows\System32\cmd.exe" /C "D:\Data\Temp\test&.bat"

        To this:

        "C:\Windows\System32\cmd.exe" /C "D:\Data\Temp\test^&.bat"

         

        Using Start-Process to demonstrate a successful launch using this method:

         

        Start-Process -FilePath '"C:\Windows\System32\cmd.exe"' -ArgumentList @('/c', '"D:\Data\Temp\test^&.bat"') -RedirectStandardError D:\Data\Temp\sp-out.txt

         

         

        Summary

        Using the ampersand in a filename isn't a good idea. That said, the underlying cause of the issue you noted is that two different command lines are produced depending on whether your simply double-click on the batch file or run it "as an administrator".

         

        The former command line is properly quoted, allowing the command to run even with the ampersand, while the latter command line is neither properly formatted nor escaped, causing the associated cmd.exe process to be created but the command within that new process to fail execution.

         

        The best solution is not to use reserved characters for any given shell within filenames but if that can't be avoided, to ensure the batch file(s) are launched using the proper escaping or quoting so the file name/path is not treated as separate commands (which is the by-design and expected outcome.)

         

        Cheers,

        Lain

Resources