在 Windows 10 上通过 cmd 中的 For 循环将文件名传递给 PowerShell 时,如何在批处理文件中转义 &(与号)和 @(At 符号)

在 Windows 10 上通过 cmd 中的 For 循环将文件名传递给 PowerShell 时,如何在批处理文件中转义 &(与号)和 @(At 符号)

我们在 Windows 10 和 Windows Server 2016/2019 上的 cmd 中使用 .cmd 批处理脚本,其中有一个“标头”,

  • 将文件复制到 %Temp% 文件夹位置,然后
  • 通过 UAC 提升提示请求管理权限。批处理文件从 %Temp% 文件夹运行后,它会
  • 从 %Temp% 文件夹中删除自身,同时保留原始文件。

这一切都很好,除非有文件

  • 文件名中的 &(与号)或
  • @(at 符号),文件名中至少有一个空格。
    但是,如果没有空格,@ 不会影响脚本。

我已经成功转义了以下字符,否则脚本将无法正常工作,例如

以下是该脚本的代码:

@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 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 5 >nul

该脚本包括ANSI 转义序列选择图形渲染 (SGR) 参数为脚本回显的文本着色。
[(左方括号)之前的字符是“”(ASCII 转义字符 不带引号)。
它不会显示在所有屏幕上,因此,我附上了此脚本的副本这里

如果批处理文件具有以下文件名,则脚本运行正常:

  • FileName12345.cmd(仅限数字和/或字母)
  • 文件名 12345.cmd(带空格的数字和/或字母)
  • (文件),;. 名称 12345.cmd(带空格的数字和/或字母以及上面的有效字符)
  • [电子邮件保护](数字和/或字母以及至少一个@符号没有任何空格

这些文件名会产生问题:

  • File&Name12345.cmd(文件名中至少有一个 & 符号)
  • 文件@Name12345.cmd(至少一个@符号至少有一个空格

有人知道如何在上面的脚本中正确地转义这些字符和任何其他字符吗?

可能有更简单的方法来创建这样的脚本,但是,高层出于某种原因只允许使用 cmd 和 PowerShell 来使用此脚本。他们也不想费心更改输入文件名,可能是出于临时的成本原因。

感谢您提供的帮助。

相关内容