[英]Batch: How to store command output with spaces in variable?
我想制作一个批处理文件来为可执行文件(例如,python)创建 Windows 防火墙规则。 为此,我有以下脚本:
REM ~ Open ports. Run with elevated administrator rights.
CALL :OPEN "python"
GOTO :EOF
:OPEN
IF ERRORLEVEL 1 (
GOTO :EOF
)
FOR /F %%i IN ('where %1') DO CALL :OPEN_PROGRAM "%1" %%i && GOTO :EOF
GOTO :EOF
:OPEN_PROGRAM
FOR %%j IN (TCP UDP) DO CALL :OPEN_PROGRAM_PORT %1 %2 "%%j"
GOTO :EOF
:OPEN_PROGRAM_PORT
netsh advfirewall firewall add rule name=%1 description=%1 dir=in action=allow edge=deferuser profile=private program=%2 protocol=%3
GOTO :EOF
只要可执行文件的路径中没有空格,就可以正常工作。
如果路径中有空格,则仅将空格之前的部分放入%%i
变量中。 我尝试使用'where /F %1'
,但它仍然会削减空间上的输出。
有没有办法将where %1
的完整输出存储在变量中? (最好不要将其写入文件)
我首先建议您不要传递没有扩展名的文件名。 这样做依赖于%PATHEXT%
下列出的每个扩展名,您可以拥有名为python.com
、 python.bat
、 python.cmd
、 python.vbs
、 python.vbe
、 python.js
、 python.jse
、 python.wsf
、 python.wsh
和python.msc
,以及python.exe
。 我相信您不会在不知不觉中为所有这些创建防火墙规则。
我还建议您不要为此使用where
命令。 原因是它可以返回多个项目。 例如,试试这个, where notepad.exe
并且如果没记错的话,您可能会看到C:\\WINDOWS\\System32\\notepad.exe
,然后是C:\\WINDOWS\\notepad.exe
。 这是因为where.exe
按列表顺序搜索%PATH%
中的每个位置,并返回每个位置,因为%PATH%
下的前两个条目默认应为C:\\WINDOWS\\system32;C:\\WINDOWS;
.
因此,我的建议是使用另一种方法,它返回在%PATH%
下找到的第一个项目,而不是所有项目,如果您正确使用了变量,这应该返回默认的(最常用的)项目。 方法是%~$PATH
变量扩展,在for
命令的帮助信息下有说明,即输入for /?
在命令提示符处。
示例脚本:
@Echo Off
SetLocal EnableExtensions
Rem ~ Open ports. Run with elevated administrator rights.
"%__AppDir__%reg.exe" Query HKU\S-1-5-19 1>NUL 2>&1 || (
Echo This script must be run elevated.
Echo Please use 'Run as administrator'
"%__AppDir__%timeout.exe" /T 3 /NoBreak 1>NUL
GoTo :EOF)
Call :OpenPorts "python.exe"
Pause
GoTo :EOF
:OpenPorts
For %%G In ("%~1") Do For %%H In (TCP UDP) Do (
"%__AppDir__%netsh.exe" AdvFirewall Firewall Add Rule^
Name="%~n1" Description="%~1" Dir=in Action=allow^
Edge=deferuser Profile=private Program="%%~$Path:G"^
Protocol=%%H)
Exit /B
我已经删除了所有不必要的Call
命令, (只使用一个) ,并故意使用插入符号来分割你的超长行,以提高可读性; (这也允许您包含localport=
和/或remoteport=
选项,我假设您的“开放端口”名称是您稍后要作为对上述内容的修改而包含的) 。 我还冒昧地包含了一些代码,以确定脚本是否正在运行,如果不是,则在关闭之前显示一条消息。
将where.exe
的输出写入文件,然后一次读取一行。 有一种方法可以在“===”行之后没有临时文件。
@ECHO OFF
SET "XTOFIND=%~1"
SET "TEMPFILE=%TEMP%\wherelist.tmp"
IF EXIST "%TEMPFILE%" (DEL "%TEMPFILE%")
"%__appdir__%where.exe" "%XTOFIND%" >"%TEMPFILE%"
FOR /F "tokens=*" %%A IN ('TYPE "%TEMPFILE%"') DO (
ECHO CALL :OPEN_PROGRAM "%%~A" %2 "%%J"
)
IF EXIST "%TEMPFILE%" (DEL "%TEMPFILE%")
ECHO ============
SET "XTOFIND=%~1"
FOR /F "tokens=*" %%A IN ('"%__appdir__%where.exe" "%XTOFIND%"') DO (
ECHO %%~A
ECHO CALL :OPEN_PROGRAM "%%~A" %2 "%%J"
)
EXIT /B 0
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.