[英]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.