我需要在运行批处理文件时传递ID和密码,而不是将它们硬编码到文件中。
以下是命令行的样子:
test.cmd admin P@55w0rd > test-log.txt
我需要在运行批处理文件时传递ID和密码,而不是将它们硬编码到文件中。
以下是命令行的样子:
test.cmd admin P@55w0rd > test-log.txt
让我们保持简单。
这是 .cmd 文件。
@echo off
rem this file is named echo_3params.cmd
echo %1
echo %2
echo %3
set v1=%1
set v2=%2
set v3=%3
echo v1 equals %v1%
echo v2 equals %v2%
echo v3 equals %v3%
这里有三个来自命令行的调用。
C:\Users\joeco>echo_3params 1abc 2 def 3 ghi
1abc
2
def
v1 equals 1abc
v2 equals 2
v3 equals def
C:\Users\joeco>echo_3params 1abc "2 def" "3 ghi"
1abc
"2 def"
"3 ghi"
v1 equals 1abc
v2 equals "2 def"
v3 equals "3 ghi"
C:\Users\joeco>echo_3params 1abc '2 def' "3 ghi"
1abc
'2
def'
v1 equals 1abc
v2 equals '2
v3 equals def'
C:\Users\joeco>
FOR %%A IN (%*) DO (
REM Now your batch file handles %%A instead of %1
REM No need to use SHIFT anymore.
ECHO %%A
)
这段代码循环遍历批处理参数(%*),无论它们是否带引号,然后输出每个参数。
这段代码循环遍历批处理参数(%*),无论它们是否带引号,然后输出每个参数。
test.bat *.txt
、test.bat cat^&dog
或者 Test.bat /?
。 - jeb我写了一个简单的read_params脚本,可以作为函数(或外部.bat
)调用,并将所有变量放入当前环境中。它不会修改原始参数,因为函数是使用原始参数的副本进行call
调用的。
例如,给定以下命令:
myscript.bat some -random=43 extra -greeting="hello world" fluff
myscript.bat
在调用函数后可以使用这些变量:
call :read_params %*
echo %random%
echo %greeting%
这是函数:
:read_params
if not %1/==/ (
if not "%__var%"=="" (
if not "%__var:~0,1%"=="-" (
endlocal
goto read_params
)
endlocal & set %__var:~1%=%~1
) else (
setlocal & set __var=%~1
)
shift
goto read_params
)
exit /B
限制
-force
。您可以使用 -force=true
,但我无法想到一种方法来允许空值,除非提前知道不会有值的参数列表。更新日志
-
来使用其他命令行参数。受@Jon在其他地方的答案启发,我制作了一个更通用的算法来提取命名参数、可选值和开关。
假设我们想要实现一个实用程序foobar
。它需要一个初始命令。它有一个可选参数--foo
,它采用一个可选值(当然不能是另一个参数);如果该值缺失,则默认为default
。它还有一个可选参数--bar
,它采用一个必需值。最后,它可以采用一个标志--baz
,不允许任何值。哦,这些参数可以按任何顺序出现。
换句话说,它看起来像这样:
foobar <command> [--foo [<fooval>]] [--bar <barval>] [--baz]
这里是一个解决方案:
@ECHO OFF
SETLOCAL
REM FooBar parameter demo
REM By Garret Wilson
SET CMD=%~1
IF "%CMD%" == "" (
GOTO usage
)
SET FOO=
SET DEFAULT_FOO=default
SET BAR=
SET BAZ=
SHIFT
:args
SET PARAM=%~1
SET ARG=%~2
IF "%PARAM%" == "--foo" (
SHIFT
IF NOT "%ARG%" == "" (
IF NOT "%ARG:~0,2%" == "--" (
SET FOO=%ARG%
SHIFT
) ELSE (
SET FOO=%DEFAULT_FOO%
)
) ELSE (
SET FOO=%DEFAULT_FOO%
)
) ELSE IF "%PARAM%" == "--bar" (
SHIFT
IF NOT "%ARG%" == "" (
SET BAR=%ARG%
SHIFT
) ELSE (
ECHO Missing bar value. 1>&2
ECHO:
GOTO usage
)
) ELSE IF "%PARAM%" == "--baz" (
SHIFT
SET BAZ=true
) ELSE IF "%PARAM%" == "" (
GOTO endargs
) ELSE (
ECHO Unrecognized option %1. 1>&2
ECHO:
GOTO usage
)
GOTO args
:endargs
ECHO Command: %CMD%
IF NOT "%FOO%" == "" (
ECHO Foo: %FOO%
)
IF NOT "%BAR%" == "" (
ECHO Bar: %BAR%
)
IF "%BAZ%" == "true" (
ECHO Baz
)
REM TODO do something with FOO, BAR, and/or BAZ
GOTO :eof
:usage
ECHO FooBar
ECHO Usage: foobar ^<command^> [--foo [^<fooval^>]] [--bar ^<barval^>] [--baz]
EXIT /B 1
SETLOCAL
让变量不会逃逸到调用环境。SET FOO=
等,以防某人在调用环境中定义了它们。%~1
去除引号。IF "%ARG%" == ""
而不是IF [%ARG%] == []
,因为以空格结尾的值与[
和]
根本不兼容。IF
块内部进行SHIFT
,当前的参数(如%~1
)也不会更新,因为它们是在解析IF
时确定的。你可以在IF
块内部使用%~1
和%~2
,但这会令人困惑,因为你有一个SHIFT
。你可以在块的末尾放置SHIFT
以获得清晰度,但这也可能会被遗漏并/或混淆人们。因此,“捕获”%~1
和%~1
在块外似乎是最好的选择。IF NOT "%ARG:~0,2%" == "--"
。SET FOO=%DEFAULT_FOO%
是遗憾的,但另一种选择是在IF NOT "%ARG%" == ""
块之外添加一个IF "%FOO%" == "" SET FOO=%DEFAULT_FOO%
。然而,由于这仍然在IF "%PARAM%" == "--foo"
块内部,所以%FOO%
值将在进入块之前被评估和设置,因此你永远不会检测到既出现了--foo
参数,同时%FOO%
的值也丢失了。ECHO Missing bar value. 1>&2
将错误消息发送到stderr。ECHO:
或其变体。要在命令行中引用设置的变量,您需要使用%a%
,例如:
set a=100
echo %a%
rem output = 100
注意:此方法仅适用于Windows 7专业版。
@echo off && setlocal EnableDelayedExpansion
for %%Z in (%*)do set "_arg_=%%Z" && set/a "_cnt+=1+0" && (
call set "_arg_[!_cnt!]=!_arg_!" && for /l %%l in (!_cnt! 1 !_cnt!
)do echo/ The argument n:%%l is: !_arg_[%%l]!
)
endlocal
@echo off && setlocal EnableDelayedExpansion
for %%Z in (%*)do set "_arg_=%%Z" && set/a "_cnt+=1+0" && call set "_arg_[!_cnt!]=!_arg_!"
fake-command /u !_arg_[1]! /p !_arg_[2]! > test-log.txt
echo off
echo "Batch started"
set arg1=%1
echo "arg1 is %arg1%"
echo on
pause
CallTest1.bat
call "C:\Temp\Test1.bat" pass123
输出
YourLocalPath>call "C:\Temp\test.bat" pass123
YourLocalPath>echo off
"Batch started"
"arg1 is pass123"
YourLocalPath>pause
Press any key to continue . . .
在此处,YourLocalPath代表当前目录路径。
为了简单起见,将命令参数存储在变量中,并使用变量进行比较。
这不仅易于编写,而且易于维护。因此,如果以后其他人或您在长时间之后阅读脚本,则很容易理解和维护。
要编写内联代码:请参见其他答案。
java %~n1
将批处理文件放在system32文件夹中,打开Java类文件,右键点击属性,选择“打开方式”,然后找到批处理文件,选中即可完成...
这对我很有效。
注:我找不到一种方法来在关闭Java类时关闭cmd窗口。暂时还没有解决方案...
start /wait java %~n1
- Paint_Ninja如果您更喜欢使用键值对来传递参数,可以使用类似以下的代码:
@echo off
setlocal enableDelayedExpansion
::::: asigning arguments as a key-value pairs:::::::::::::
set counter=0
for %%# in (%*) do (
set /a counter=counter+1
set /a even=counter%%2
if !even! == 0 (
echo setting !prev! to %%#
set "!prev!=%%~#"
)
set "prev=%%~#"
)
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: showing the assignments
echo %one% %two% %three% %four% %five%
endlocal
c:>argumentsDemo.bat one 1 "two" 2 three 3 four 4 "five" 5
1 2 3 4 5
您还可以预先设置某些环境变量。这可以通过在控制台中设置它们或从我的计算机设置它们来完成:
@echo off
if defined variable1 (
echo %variable1%
)
if defined variable2 (
echo %variable2%
)
并像这样调用:
c:\>set variable1=1
c:\>set variable2=2
c:\>argumentsTest.bat
1
2
您也可以指向一个预设所需数值的文件。 如果这是脚本:
@echo off
setlocal
::::::::::
set "VALUES_FILE=E:\scripts\values.txt"
:::::::::::
for /f "usebackq eol=: tokens=* delims=" %%# in ("%VALUES_FILE%") do set "%%#"
echo %key1% %key2% %some_other_key%
endlocal
:::: use EOL=: in the FOR loop to use it as a comment
key1=value1
key2=value2
:::: do not left spaces arround the =
:::: or at the begining of the line
some_other_key=something else
and_one_more=more
如果您担心安全/密码盗窃(这导致您设计了此解决方案,在执行时获取登录凭据而无需数据库的静态硬编码),那么您可以将密码解密或解密密钥的API或代码的一半存储在程序文件中,因此在运行时,用户将在控制台中键入用户名/密码以进行哈希/解密,然后再通过set /p
传递给程序代码以执行,如果您正在查看用户在运行时输入凭据。
如果您正在运行脚本以使用各种用户/密码运行程序,则命令行参数适合您。
如果您正在创建测试文件以查看不同登录的输出/效果,则可以将所有登录信息存储在加密文件中,作为参数传递给test.cmd,除非您想坐在命令行上并键入所有登录信息直到完成。
可以提供的参数数量受命令行上的总字符数限制。为了克服这个限制,前面的段落技巧是一个解决方法,而不会冒险暴露用户密码。