We are using a .cmd batch script in cmd on Windows 10 and Windows Server 2016/2019 with a “header” that
- copies the file to the %Temp% folder location and then
- requests administrative privileges via a UAC elevation prompt. After the batch file runs from the %Temp% folder, it
- deletes itself from the %Temp% folder while keeping the original file.
This all works fine unless there are files with
- & (ampersand) in the file name or
- @ (at sign) with at least one space in the file name.
However, without spaces, @s don’t bother the script.
I have successfully escaped the following characters that would stop the script from working otherwise, e.g.
- (
- )
- ,
- ;
Here is the code for the script:
@echo off
Title %~n0
GoTo Begin
:End
::"Self-destruction" part that deletes batch file copy in %Temp% folder and confirms whether file was actually deleted.
Start /min cmd /c (@echo off^&Title "%~nx0" Temp Batch File Deletion^&echo [93mDeleting file "%Temp%%~nx0" . . . [39m^&TimeOut 5 /NoBreak ^>nul 2^>^&1^&Del /a "%Temp%%~nx0"^&ClS^&If Exist "%Temp%%~nx0" ^(echo [91mFile "%Temp%%~nx0" could not be deleted![39m^&Pause ^>nul 2^>^&1^) else ^(echo [92mFile "%Temp%%~nx0" deleted successfully![39m^&TimeOut 5 /NoBreak ^>nul 2^>^&1^))
If NOT Defined Elev (@TimeOut 5 /NoBreak >nul 2>&1)
GoTo :EoF
:Begin
::Setting variable %_nx0% derived from %~nx0 with several characters escaped for copying file to %Temp% folder
Set "_nx0=%~nx0"
Set "_nx0=%_nx0:(=^(%"
Set "_nx0=%_nx0:)=^)%"
Set "_nx0=%_nx0:,=^,%"
Set "_nx0=%_nx0:;=^;%"
Set "_nx0=%_nx0:&=^&%"
Set "_nx0=%_nx0:@=^@%"
Set "_nx0=%_nx0: =^ %"
::Setting variable %_dpnx0% derived from %~dpnx0 with several characters escaped for passing file name to PowerShell
Set "_dpnx0=%~dpnx0"
Set "_dpnx0=%_dpnx0:)=^)%"
Set "_dpnx0=%_dpnx0:,=^,%"
Set "_dpnx0=%_dpnx0:;=^;%"
::How to escape & and @ for passing to PowerShell's "Start-Process" in when in a cmd "For" loop?
Set "_dpnx0=%_dpnx0:&=^^^&%"
Set "_dpnx0=%_dpnx0:@=^^^@%"
Set "_dpnx0=%_dpnx0: =^ %"
::Just a test line to debug new variables
::echo %_nx0%&echo %_dpnx0%&TimeOut 3 >nul
::Commands to confirm whether file is in %Temp% folder and to copy it there if it isn't
If NOT "%~dp0" == "%Temp%" (Copy /y "%~dpnx0" "%Temp%" >nul 2>&1&&Start cmd /c "%Temp%%_nx0%"&&exit /b)
::Commands to confirm via PowerShell command whether file is run with admin privileges and to request them by restarting script via PowerShell's "-Verb RunAs" command if file is run without admin privileges
::a "For" loop is used to set variable %Elev% to pass elevation confirmation from PowerShell's "$?" command back to cmd as "True" or "False"
::If file is run with admin privileges run :Main part below and end script with :End self-destruction command above
::If File is run without admin privileges end script via ":EoF" command
net file >nul 2>&1
If %ErrorLevel%==0 (Call :Main&GoTo End) Else (
For /f "Tokens=* UseBackQ" %%f in (`PowerShell -NoLogo -Command "& { Start-Process "%_dpnx0%" -Verb RunAs;$? }"`) Do (Set "Elev=%%f"))
If %Elev%==False (GoTo End) else (GoTo :EoF)
:Main
::Main part of script after header
echo [38;5;202mTesting the batch header . . . [39
TimeOut /t 5 >nul
This script includes ANSI escape sequence Select Graphic Rendition (SGR) parameters to color the text echoed by the script.
The character before [ (opening square bracket) is “” (ASCII escape character without quotes).
It doesn’t show up on all screens, therefore, I have inluded a copy of this script here.
If the batch files have the following file names, the script runs fine:
- FileName12345.cmd (just numbers and/or letters)
- File Name 12345.cmd (numbers and/or letters with spaces)
- (File), ; . Name 12345.cmd (numbers and/or letters with spaces and the working characters from above)
- File@Name12345.cmd (numbers and/or letters and at least one @ sign without any spaces)
These file names create problems:
- File&Name12345.cmd (at least one & sign in the file name)
- File @ Name12345.cmd (at least one @ sign with at least one space)
Does anyone know how to escape these and any other characters correctly in the script above?
There may be easier ways of creating such a script, however, the higher-ups only greenlight the usage of this script using cmd and PowerShell for whatever reasons. They also don’t want to bother with changing the input file names probably for ad-hoc cost reasons.
Thanks for any help with this.