我想找到一个Windows批处理对应Bash的$@
,其中包含传递给脚本的所有参数的列表。
或者我不得不打扰shift
?
答案 0 :(得分:548)
dancavallaro没错,%*
表示所有命令行参数(不包括脚本名称本身)。您可能还会发现这些有用:
%0
- 用于调用批处理文件的命令(可以是foo
,..\foo
,c:\bats\foo.bat
等。)
%1
是第一个命令行参数,
%2
是第二个命令行参数,
等等%9
(和SHIFT
可以用于第9次之后的那些人)。
%~nx0
- 批处理文件的实际名称,无论调用方法如何(some-batch.bat)
%~dp0
- 脚本的驱动器和路径(d:\ scripts)
%~dpnx0
- 是脚本的完全限定路径名(d:\ scripts \ some-batch.bat)
https://www.ss64.com/nt/syntax-args.html和https://www.robvanderwoude.com/parameters.html
的更多信息示例答案 1 :(得分:132)
%*
似乎保存了传递给脚本的所有参数。
答案 2 :(得分:60)
%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
并在%1
语句后展开rem
(也适用于%2 ..%*)。
但是为了能够重定向echo on
的输出,您需要两个FOR-LOOPS。
额外字符* #
用于对/?
之类的内容安全(会显示REM的帮助)。
或者行末端的插入符号^可以用作多行字符。
FOR / F应该使用延迟扩展,否则内容为“!”会被摧毁
删除param1
中的额外字符后你就明白了。
要以安全的方式使用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
答案 3 :(得分:45)
我发现下次需要查看这些信息时。您可以在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 %*
答案 4 :(得分:19)
将所有args检索到脚本的方法如下:
@ECHO off
ECHO The %~nx0 script args are...
for %%I IN (%*) DO ECHO %%I
pause
答案 5 :(得分:4)
这是获取args并将其设置为env vars的一种相当简单的方法。在这个例子中,我将它们称为键和值。
将以下代码示例保存为“args.bat”。然后调用批处理文件 您从命令行保存。 例如:arg.bat --x 90 --y 120
我提供了一些echo命令来引导您完成整个过程。但是 最终结果是--x将具有值90并且--y将具有值120(即,如果您运行上面指定的示例;-))。
然后,您可以使用'if defined'条件语句来确定是否运行代码块。 所以让我们说: “arg.bat --x你好世界” 然后我可以使用语句“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
答案 6 :(得分:2)
以下代码模拟数组('params
') - 获取脚本收到的参数并将其存储在变量params_1
.. params_n
中,其中{{1} } = n
=数组元素的数量:
params_0
答案 7 :(得分:1)
如果引号中的参数包含空格,则%*
将无法正常工作。
我发现最好的解决方案是有一个连接所有参数的循环: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)
答案 8 :(得分:1)
要使用循环,请以纯批处理的形式获取所有参数:
@echo off && setlocal EnableDelayedExpansion
set "_cnt=0" && for %%Z in (%*) do (
set "_arg_=%%Z" && set /a "_cnt=!_cnt! + 1" && set "_arg_[!_cnt!]=!_arg_!"
shift && for /l %%l in (!_cnt! 1 !_cnt!) do echo/ The argument n:%%l is: !_arg_[%%l]!
)
goto :eof
您的代码已准备就绪,可以在需要的地方使用其参数编号,例如...
@echo off && setlocal EnableDelayedExpansion
set "_cnt=0" && for %%Z in (%*) do (
set "_arg_=%%Z" && set /a "_cnt=!_cnt! + 1" && set "_arg_[!_cnt!]=!_arg_!"
shift
)
run_command !_arg_[1]! !_arg_[2]! !_arg_[2]!> log.txt
答案 9 :(得分:0)
@echo off :start :: Insert your code here echo.%%1 is now:%~1 :: End insert your code here if "%~2" NEQ "" ( shift goto :start )
答案 10 :(得分:0)
上面提供的大量信息让我进一步研究并最终得到了答案,所以我想贡献我最后做的事情,希望能帮到别人:
我还希望将不同数量的变量传递给批处理文件,以便可以在文件中处理它们。
我可以使用引号
我希望它们的处理方式与下面类似 - 但是使用循环而不是手动写出:
所以我想执行这个:
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
)
UPDATE - 我不得不修改为下面的代码,我在尝试引用%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
)
答案 11 :(得分:0)
您可以使用For
来获取Arg列表。
Help = For /?
Help = Setlocal /?
这是我的方式=
@echo off
::For Run Use This = cmd /c ""Args.cmd" Hello USER programming-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
不需要换档命令!
答案 12 :(得分:0)
有时我需要提取几个命令行参数,但不是全部,而不是从第一个中提取。让我们假设以下调用:
Test.bat uno dos tres cuatro cinco seis siete
当然,至少在同一文件夹中有test.exe时,不需要扩展名“ .bat”。我们想要的是获得输出“ tres cuatro cinco”(无论是一行还是三行)。目标是只有我需要三个参数,并且从第三个参数开始。为了有一个简单的例子,每个动作都只是“回声”,但是您可以考虑对所选参数进行其他更复杂的动作。
我提供了一些示例(选项),以便您可以查看哪个更适合您。不幸的是,在诸如“(%3,1,%5)中的%% i”之类的范围内,没有一种基于for循环的好方法(或者我不知道)。
@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
可能您可以找到更多选项或将多个选项组合在一起。享受它们。
答案 13 :(得分:-1)
Windows版本(虽然需要socat)
C:\Program Files (x86)\Git\bin>type gitproxy.cmd
socat STDIO PROXY:proxy.mycompany.de:%1:%2,proxyport=3128
设置:
C:\Users\exhau\AppData\Roaming\npm>git config --global core.gitproxy gitproxy.cmd