如何获得参数列表?

我想找到一个Windows批处理对应Bash的$@,它持有传递到脚本的所有参数的列表。

或者我不得不麻烦shift?

459496 次浏览

%*似乎包含了传递给脚本的所有参数。

dancavallaro是正确的,%*用于所有命令行参数(不包括脚本名称本身)。你可能还会发现这些有用:

%0 -用于调用批处理文件的命令(可以是foo..\fooc:\bats\foo.bat%1是第一个命令行参数,
%2是第二个命令行参数,
等等,直到%9(而SHIFT可以用于9号之后的那些)。< / p >

%~nx0 -批处理文件的实际名称,不管调用方法(some-batch.bat)如何 %~dp0 -脚本(d:\scripts)的驱动器和路径
%~dpnx0 -是脚本的完全限定路径名(d:\scripts\some-batch.bat)

更多的信息示例在https://www.ss64.com/nt/syntax-args.htmlhttps://www.robvanderwoude.com/parameters.html

< p > %1……%n%*保存参数,但访问它们可能很棘手,因为内容将被解释 因此,使用正常语句

是不可能处理这样的事情的
myBatch.bat "&"^&

每一行都失败,因为cmd.exe试图执行一个&号(%1的内容是"&"&)

set var=%1
set "var=%1"
set var=%~1
set "var=%~1"

但是存在一个临时文件的解决方案

@echo off
SETLOCAL DisableDelayedExpansion


SETLOCAL
for %%a in (1) do (
set "prompt=$_"
echo on
for %%b in (1) do rem * #%1#
@echo off
) > param.txt
ENDLOCAL


for /F "delims=" %%L in (param.txt) do (
set "param1=%%L"
)
SETLOCAL EnableDelayedExpansion
set "param1=!param1:*#=!"
set "param1=!param1:~0,-2!"
echo %%1 is '!param1!'
窍门是启用echo on并在rem语句后展开%1(也适用于%2 ..% *)。< br > 但是为了能够重定向echo on的输出,你需要两个FOR-LOOPS。< / p > 额外的字符* #用于安全对抗诸如/?之类的内容(将显示REM的帮助) 或者行尾的插入符号^可以作为多行字符。< / p >

FOR /F必须关闭延迟展开,否则包含"!"的内容将被销毁 在删除param1中的额外字符后,你就得到了它。< / p >

为了以安全的方式使用param1,启用延迟扩展。

编辑:一条注释到%0

%0包含用于调用批处理的命令,也像FoO.BaT
一样保留大小写 但是在调用函数之后,%0%~0中也包含函数名(或者更好的是用于调用函数的字符串) 但是使用%~f0,你仍然可以回忆起文件名

@echo off
echo main %0, %~0, %~f0
call :myLabel+xyz
exit /b


:MYlabel
echo func %0, %~0, %~f0
exit /b

输出

main test.bat, test.bat, C:\temp\test.bat
func :myLabel+xyz, :myLabel+xyz, C:\temp\test.bat

我发现下次你需要查这些资料的时候。你可以在cmd中输入call /?,而不是打开浏览器并谷歌它,你会得到它:

...


%* in a batch script refers to all the arguments (e.g. %1 %2 %3
%4 %5 ...)


Substitution of batch parameters (%n) has been enhanced.  You can
now use the following optional syntax:


%~1         - expands %1 removing any surrounding quotes (")
%~f1        - expands %1 to a fully qualified path name
%~d1        - expands %1 to a drive letter only
%~p1        - expands %1 to a path only
%~n1        - expands %1 to a file name only
%~x1        - expands %1 to a file extension only
%~s1        - expanded path contains short names only
%~a1        - expands %1 to file attributes
%~t1        - expands %1 to date/time of file
%~z1        - expands %1 to size of file
%~$PATH:1   - searches the directories listed in the PATH
environment variable and expands %1 to the fully
qualified name of the first one found.  If the
environment variable name is not defined or the
file is not found by the search, then this
modifier expands to the empty string


The modifiers can be combined to get compound results:


%~dp1       - expands %1 to a drive letter and path only
%~nx1       - expands %1 to a file name and extension only
%~dp$PATH:1 - searches the directories listed in the PATH
environment variable for %1 and expands to the
drive letter and path of the first one found.
%~ftza1     - expands %1 to a DIR like output line


In the above examples %1 and PATH can be replaced by other
valid values.  The %~ syntax is terminated by a valid argument
number.  The %~ modifiers may not be used with %*

获取脚本中所有参数的方法如下:

@ECHO off
ECHO The %~nx0 script args are...
for %%I IN (%*) DO ECHO %%I
pause

这里有一个相当简单的方法来获取参数并将它们设置为env vars。在本例中,我将它们称为键和值。

将下面的代码示例保存为“args.bat”。然后调用批处理文件 从命令行保存。 例如:argb .bat——x 90——y 120

我已经提供了一些echo命令来逐步完成这个过程。但是, 最终结果是——x将有一个90的值,而——y将有一个120的值(如果你运行上面指定的例子;-)) 然后,您可以使用'if defined'条件语句来决定是否运行您的代码块。 让我们运行: bat -x hello-world 然后,我可以使用语句“IF DEFINED—x echo %—x%”,结果将是“hello-world”。如果你运行批处理,这应该更有意义
@setlocal enableextensions enabledelayedexpansion
@ECHO off
ECHO.
ECHO :::::::::::::::::::::::::: arg.bat example :::::::::::::::::::::::::::::::
ECHO :: By:      User2631477, 2013-07-29                                   ::
ECHO :: Version: 1.0                                                         ::
ECHO :: Purpose: Checks the args passed to the batch.                        ::
ECHO ::                                                                      ::
ECHO :: Start by gathering all the args with the %%* in a for loop.          ::
ECHO ::                                                                      ::
ECHO :: Now we use a 'for' loop to search for our keys which are identified  ::
ECHO :: by the text '--'. The function then sets the --arg ^= to the next    ::
ECHO :: arg. "CALL:Function_GetValue" ^<search for --^> ^<each arg^>         ::
ECHO ::                                                                      ::
ECHO ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::


ECHO.


ECHO ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
ECHO :: From the command line you could pass... arg.bat --x 90 --y 220       ::
ECHO ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
ECHO.
ECHO.Checking Args:"%*"


FOR %%a IN (%*) do (
CALL:Function_GetValue "--","%%a"
)


ECHO.
ECHO ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
ECHO :: Now lets check which args were set to variables...                   ::
ECHO ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
ECHO.
ECHO ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
ECHO :: For this we are using the CALL:Function_Show_Defined "--x,--y,--z"   ::
ECHO ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
ECHO.
CALL:Function_Show_Defined "--x,--y,--z"
endlocal
goto done


:Function_GetValue


REM First we use find string to locate and search for the text.
echo.%~2 | findstr /C:"%~1" 1>nul


REM Next we check the errorlevel return to see if it contains a key or a value
REM and set the appropriate action.


if not errorlevel 1 (
SET KEY=%~2
) ELSE (
SET VALUE=%~2
)
IF DEFINED VALUE (
SET %KEY%=%~2
ECHO.
ECHO ::::::::::::::::::::::::: %~0 ::::::::::::::::::::::::::::::
ECHO :: The KEY:'%KEY%' is now set to the VALUE:'%VALUE%'                     ::
ECHO :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
ECHO.
ECHO %KEY%=%~2
ECHO.
REM It's important to clear the definitions for the key and value in order to
REM search for the next key value set.
SET KEY=
SET VALUE=
)
GOTO:EOF


:Function_Show_Defined
ECHO.
ECHO ::::::::::::::::::: %~0 ::::::::::::::::::::::::::::::::
ECHO :: Checks which args were defined i.e. %~2
ECHO :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
ECHO.
SET ARGS=%~1
for %%s in (%ARGS%) DO (
ECHO.
ECHO :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
ECHO :: For the ARG: '%%s'
IF DEFINED %%s (
ECHO :: Defined as: '%%s=!%%s!'
) else (
ECHO :: Not Defined '%%s' and thus has no value.
)
ECHO :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
ECHO.
)
goto:EOF


:done
@echo off
:start


:: Insert your code here
echo.%%1 is now:%~1
:: End insert your code here


if "%~2" NEQ "" (
shift
goto :start
)

下面的代码模拟了一个数组('params')——接受脚本接收到的参数,并将它们存储在变量params_1中。params_n,其中n=params_0=数组的元素数:

@echo off


rem Storing the program parameters into the array 'params':
rem Delayed expansion is left disabled in order not to interpret "!" in program parameters' values;
rem however, if a parameter is not quoted, special characters in it (like "^", "&", "|") get interpreted at program launch
set /a count=0
:repeat
set /a count+=1
set "params_%count%=%~1"
shift
if defined params_%count% (
goto :repeat
) else (
set /a count-=1
)
set /a params_0=count


rem Printing the program parameters stored in the array 'params':
rem After the variables params_1 .. params_n are set with the program parameters' values, delayed expansion can
rem be enabled and "!" are not interpreted in the variables params_1 .. params_n values
setlocal enabledelayedexpansion
for /l %%i in (1,1,!params_0!) do (
echo params_%%i: "!params_%%i!"
)
endlocal


pause
goto :eof

上面的很多信息引导我进行了进一步的研究,最终得出了我的答案,所以我想贡献我所做的事情,希望它能帮助其他人:

  • 我还想向批处理文件传递不同数量的变量,以便在文件中处理它们。

  • 我可以使用引号将它们传递给批处理文件

  • 我希望他们处理类似于下面-但使用循环而不是手动写入:

所以我想执行这个:

prog_ZipDeleteFiles.bat "_appPath=C:\Services\Logs\PCAP" "_appFile=PCAP*.?"

通过for循环的魔力在批处理文件中做到这一点:

set "_appPath=C:\Services\Logs\PCAP"
set "_appFile=PCAP*.?"

我遇到的问题是,我使用for循环的所有尝试都不起作用。下面的例子:

for /f "tokens* delims= " in %%A (%*) DO (
set %%A
)

会这样做:

set "_appPath=C:\Services\Logs\PCAP"

而不是:

set "_appPath=C:\Services\Logs\PCAP"
set "_appFile=PCAP*.?"

即使在设置之后

SETLOCAL EnableDelayedExpansion

原因是for循环读取了整行,并在循环的第一次迭代中将第二个参数赋值给%%B。因为%*表示所有的参数,所以只需要处理一行——因此只会发生一次for循环。事实证明,这是故意的,而我的逻辑是错误的。

因此,我不再尝试使用for循环,而是通过使用if、shift和goto语句来简化我试图做的事情。同意,这有点黑,但它更适合我的需要。我可以遍历所有参数,然后在处理完所有参数后使用if语句退出循环。

我想要实现的目标是:

echo on
:processArguments
:: Process all arguments in the order received
if defined %1 then (
set %1
shift
goto:processArguments
) ELSE (
echo off
)

更新-我不得不修改如下,当我试图引用%1并以这种方式使用shift时,我暴露了所有的环境变量:

echo on
shift
:processArguments
:: Process all arguments in the order received
if defined %0 then (
set %0
shift
goto:processArguments
) ELSE (
echo off
)
如果参数在引号中包含空格,%*将不能正确工作。 我发现的最好的解决方案是有一个循环连接所有参数:https://serverfault.com/a/22541

set args=%1
shift
:start
if [%1] == [] goto done
set args=%args% %1
shift
goto start


:done
(use %args% here)

enter image description here

对于使用循环获取所有参数,并且是纯批处理:

奥林匹克广播服务公司:用于没有:?*&<>


@echo off && setlocal EnableDelayedExpansion


for %%Z in (%*)do set "_arg_=%%Z" && set/a "_cnt+=1+0" && call set "_arg_[!_cnt!]=!_arg_!")


:: write/test these arguments/parameters ::
for /l %%l in (1 1 !_cnt!)do echo/ The argument n:%%l is: !_arg_[%%l]!


goto :eof

你的代码已经准备好在需要的地方用参数号做一些事情,比如……

@echo off && setlocal EnableDelayedExpansion


for %%Z in (%*)do set "_arg_=%%Z" && set/a "_cnt+=1+0" && call set "_arg_[!_cnt!]=!_arg_!"


echo= !_arg_[1]! !_arg_[2]! !_arg_[2]!> log.txt

你可以使用For命令获取参数列表。

帮助:For /? 帮助:Setlocal /?

这是我的方法=

@echo off
::For Run Use This = cmd /c ""Args.cmd" Hello USER Scientist etc"
setlocal EnableDelayedExpansion
set /a Count=0
for %%I IN (%*) DO (
Echo Arg_!Count! = %%I
set /a Count+=1
)
Echo Count Of Args = !Count!
Endlocal

不需要Shift命令。

有时我需要提取几个命令行参数,但不是全部,也不是从第一个参数提取。让我们假设下面的调用:

Test.bat uno dos tres cuatro cinco seis siete

当然,扩展名“。bat”是不需要的,至少你在同一个文件夹中有test.exe。我们想要的是得到输出“tres cuatro cinco”(不管是一行还是三行)。我们的目标是只需要三个参数,并从第三个参数开始。为了有一个简单的例子,每个操作都是“echo”,但是你可以考虑其他一些更复杂的操作。

我提供了一些例子,(选项),以便你可以看看你认为哪个更适合你。不幸的是,没有一个好的(或者我不知道)方法基于范围内的for循环,比如“for %% I in(%3, 1, %5)”。

@echo off
setlocal EnableDelayedExpansion


echo Option 1: one by one (same line)
echo %3, %4, %5
echo.


echo Option 2: Loop For one by one
for %%a in (%3, %4, %5) do echo %%a
echo.


echo Option 3: Loop For with check of limits
set i=0
for %%a in (%*) do (
set /A i=i+1
If !i! GTR 2 if !i! LSS 6 echo %%a
)
echo.


echo Option 4: Loop For with auxiliary list
for /l %%i in (3,1,5) do  (
set a=%%i
set b=echo %%
set b=!b!!a!
call !b!
)
echo.


echo Option 5: Assigning to an array of elements previously
set e[0]=%0
set i=0
for %%a in (%*) do (
set /A i=i+1
set e[!i!]=%%a
)
for  /l %%i in (3,1,5) do (
echo !e[%%i]!
)
echo.


echo Option 6: using shift and goto loop. It doesn't work with for loop
set i=2
:loop6
set /A i=i+1
echo %3
shift
If %i% LSS 5 goto :loop6

也许你可以找到更多的选项,或者将几个选项结合起来。享受其中的乐趣。