test.cmd admin P@55w0rd > test-log.txt
2293433 次浏览

echo offset arg1=%1set arg2=%2shiftshiftfake-command /u %arg1% /p %arg2% %*

test-command admin password foo bar

fake-command /u admin /p password admin password foo bar

IF %1.==. GOTO No1IF %2.==. GOTO No2... do stuff...GOTO End1
:No1ECHO No param 1GOTO End1:No2ECHO No param 2GOTO End1
:End1

@fake-command /u %1 /p %2

test.cmd admin P@55w0rd > test-log.txt

%1适用于第一个参数,%2(这是棘手的部分)适用于第二个。您最多可以以这种方式传递9个参数。

创建一个新的批处理文件(例如:openclass.bat)并在文件中写入以下行:

java %~n1

然后将批处理文件放置在,比方说,system 32文件夹,转到您的Java类文件,右键单击,属性,打开…,然后找到您的批处理文件,选择它,就是这样…

它为我工作。

PS:关闭Java类时找不到关闭cmd窗口的方法。暂时…

访问批处理参数可以简单地使用%1、%2、…%9或%*,
#36825;内容很简单

对于像"&"^&这样的复杂内容,没有简单的方法,因为不可能在不产生错误的情况下访问%1。

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

线条扩展到

set  var="&"&set "var="&"&"set  var="&"&set "var="&"&"

每一行都失败,因为其中一个&在引号之外。

可以通过从临时文件中读取版本的参数来解决。

@echo offSETLOCAL DisableDelayedExpansion
SETLOCALfor %%a in (1) do (set "prompt="echo onfor %%b in (1) do rem * #%1#@echo off) > param.txtENDLOCAL
for /F "delims=" %%L in (param.txt) do (set "param1=%%L")SETLOCAL EnableDelayedExpansionset "param1=!param1:*#=!"set "param1=!param1:~0,-2!"echo %%1 is '!param1!'

诀窍是启用echo on并在rem语句后展开%1(也适用于%2 .. %*)。
因此,即使是"&"&也可以在不产生错误的情况下进行响应,正如所说。

但是为了能够重定向echo on的输出,您需要两个for循环。

额外的字符* #用于防止像/?这样的内容(将显示REM的帮助)。
或者行尾的插入符号^可以用作多行字符,即使在rem之后。

然后从文件中读取rem参数输出,但要小心。
/F应该延迟扩展关闭,否则带有“!”的内容将被销毁。删除param1中的额外字符后,您就得到了它。

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

没有必要使它复杂化。它只是命令%1%2参数,例如,

@echo off
xcopy %1 %2 /D /E /C /Q /H /R /K /Y /Z
echo copied %1 to %2
pause

“暂停”显示批处理文件已完成的操作并等待您按下ANY键。将其保存为Windows文件夹中的xx.bat。

要使用它,键入,例如:

xx c:\f\30\*.* f:\sites\30

这个批处理文件处理所有必要的参数,比如只复制文件,更新的文件等。我在Windows之前就使用过它。如果您想在复制文件时看到文件的名称,请省略Q参数。

要在命令行中引用设置变量,您需要使用%a%,例如:

set a=100echo %a%rem output = 100

注意:这适用于Windows 7 Pro。

@ECHO OFF:LoopIF "%1"=="" GOTO ContinueSHIFTGOTO Loop:Continue

注意:如果%1本身包含在引号中,则IF"%1"==""会导致问题。

在这种情况下,使用IF [%1]==[]或在NT 4(SP6)和更高版本中使用IF "%~1"==""

FOR %%A IN (%*) DO (REM Now your batch file handles %%A instead of %1REM No need to use SHIFT anymore.ECHO %%A)

这会循环遍历批处理参数(%*),无论它们是否被引用,然后回显每个参数。

让我们保持简单。

这是. cmd文件。

@echo offrem this file is named echo_3params.cmdecho %1echo %2echo %3set v1=%1set v2=%2set v3=%3echo v1 equals %v1%echo v2 equals %v2%echo v3 equals %v3%

以下是来自命令行的3个调用。

C:\Users\joeco>echo_3params 1abc 2 def  3 ghi1abc2defv1 equals 1abcv2 equals 2v3 equals def
C:\Users\joeco>echo_3params 1abc "2 def"  "3 ghi"1abc"2 def""3 ghi"v1 equals 1abcv2 equals "2 def"v3 equals "3 ghi"
C:\Users\joeco>echo_3params 1abc '2 def'  "3 ghi"1abc'2def'v1 equals 1abcv2 equals '2v3 equals def'
C:\Users\joeco>

我写了一个简单的read_params脚本,可以作为函数(或外部.bat)调用,并将所有变量放入当前环境中。它不会修改原始参数,因为函数正在call编辑原始参数的副本。

例如,给定以下命令:

myscript.bat some -random=43 extra -greeting="hello world" fluff

myscript.bat将能够在调用函数后使用变量:

call :read_params %*
echo %random%echo %greeting%

下面是函数:

:read_paramsif not %1/==/ (if not "%__var%"=="" (if not "%__var:~0,1%"=="-" (endlocalgoto read_params)endlocal & set %__var:~1%=%~1) else (setlocal & set __var=%~1)shiftgoto read_params)exit /B

限制

  • 无法加载没有值的参数,例如-force。您可以使用-force=true,但我想不出一种方法来允许空白值,而不会提前知道没有值的参数列表。

更新日志

  • 2/18/2016
    • 不再需要延迟扩展
    • 现在通过在参数之前查找-来处理其他命令行参数。

一个朋友最近问我这个问题,所以我想我应该发布我如何处理批处理文件中的命令行参数。

如您所见,这种技术有一点开销,但它使我的批处理文件非常容易理解和快速实现。以及支持以下结构:

>template.bat [-f] [--flag] [--namedvalue value] arg1 [arg2][arg3][...]

它的关键是具有:init:parse:main函数。

示例用法

>template.bat /?test v1.23This is a sample batch file template,providing command-line arguments and flags.
USAGE:test.bat [flags] "required argument" "optional argument"
/?, --help           shows this help/v, --version        shows the version/e, --verbose        shows detailed output-f, --flag value     specifies a named parameter value
>template.bat          <- throws missing argument error(same as /?, plus..)****                                   ********    MISSING "REQUIRED ARGUMENT"    ********                                   ****
>template.bat -v1.23
>template.bat --versiontest v1.23This is a sample batch file template,providing command-line arguments and flags.
>template.bat -e arg1**** DEBUG IS ONUnNamedArgument:    "arg1"UnNamedOptionalArg: not providedNamedFlag:          not provided
>template.bat --flag "my flag" arg1 arg2UnNamedArgument:    "arg1"UnNamedOptionalArg: "arg2"NamedFlag:          "my flag"
>template.bat --verbose "argument #1" --flag "my flag" second**** DEBUG IS ONUnNamedArgument:    "argument #1"UnNamedOptionalArg: "second"NamedFlag:          "my flag"

template.bat

@::!/dos/rocks@echo offgoto :init
:headerecho %__NAME% v%__VERSION%echo This is a sample batch file template,echo providing command-line arguments and flags.echo.goto :eof
:usageecho USAGE:echo   %__BAT_NAME% [flags] "required argument" "optional argument"echo.echo.  /?, --help           shows this helpecho.  /v, --version        shows the versionecho.  /e, --verbose        shows detailed outputecho.  -f, --flag value     specifies a named parameter valuegoto :eof
:versionif "%~1"=="full" call :header & goto :eofecho %__VERSION%goto :eof
:missing_argumentcall :headercall :usageecho.echo ****                                   ****echo ****    MISSING "REQUIRED ARGUMENT"    ****echo ****                                   ****echo.goto :eof
:initset "__NAME=%~n0"set "__VERSION=1.23"set "__YEAR=2017"
set "__BAT_FILE=%~0"set "__BAT_PATH=%~dp0"set "__BAT_NAME=%~nx0"
set "OptHelp="set "OptVersion="set "OptVerbose="
set "UnNamedArgument="set "UnNamedOptionalArg="set "NamedFlag="
:parseif "%~1"=="" goto :validate
if /i "%~1"=="/?"         call :header & call :usage "%~2" & goto :endif /i "%~1"=="-?"         call :header & call :usage "%~2" & goto :endif /i "%~1"=="--help"     call :header & call :usage "%~2" & goto :end
if /i "%~1"=="/v"         call :version      & goto :endif /i "%~1"=="-v"         call :version      & goto :endif /i "%~1"=="--version"  call :version full & goto :end
if /i "%~1"=="/e"         set "OptVerbose=yes"  & shift & goto :parseif /i "%~1"=="-e"         set "OptVerbose=yes"  & shift & goto :parseif /i "%~1"=="--verbose"  set "OptVerbose=yes"  & shift & goto :parse
if /i "%~1"=="--flag"     set "NamedFlag=%~2"   & shift & shift & goto :parseif /i "%~1"=="-f"         set "NamedFlag=%~2"   & shift & shift & goto :parse
if not defined UnNamedArgument     set "UnNamedArgument=%~1"     & shift & goto :parseif not defined UnNamedOptionalArg  set "UnNamedOptionalArg=%~1"  & shift & goto :parse
shiftgoto :parse
:validateif not defined UnNamedArgument call :missing_argument & goto :end
:mainif defined OptVerbose (echo **** DEBUG IS ON)
echo UnNamedArgument:    "%UnNamedArgument%"
if defined UnNamedOptionalArg      echo UnNamedOptionalArg: "%UnNamedOptionalArg%"if not defined UnNamedOptionalArg  echo UnNamedOptionalArg: not provided
if defined NamedFlag               echo NamedFlag:          "%NamedFlag%"if not defined NamedFlag           echo NamedFlag:          not provided
:endcall :cleanupexit /B
:cleanupREM The cleanup function is only really necessary if youREM are _not_ using SETLOCAL.set "__NAME="set "__VERSION="set "__YEAR="
set "__BAT_FILE="set "__BAT_PATH="set "__BAT_NAME="
set "OptHelp="set "OptVersion="set "OptVerbose="
set "UnNamedArgument="set "UnNamedArgument2="set "NamedFlag="
goto :eof

受@Jon的在别处回答的启发,我设计了一个更通用的算法来提取命名参数、可选值和开关。

假设我们要实现一个实用程序foobar。它需要一个初始命令。它有一个可选参数--foo,它接受可选值(当然不能是另一个参数);如果缺少该值,它默认为default。它还有一个可选参数--bar,它接受选填/必填值。最后它可以接受一个不允许值的标志--baz。哦,这些参数可以按任何顺序出现。

换句话说,它看起来像这样:

foobar <command> [--foo [<fooval>]] [--bar <barval>] [--baz]

这里有一个解决方案:

@ECHO OFFSETLOCALREM FooBar parameter demoREM By Garret Wilson
SET CMD=%~1
IF "%CMD%" == "" (GOTO usage)SET FOO=SET DEFAULT_FOO=defaultSET BAR=SET BAZ=
SHIFT:argsSET PARAM=%~1SET ARG=%~2IF "%PARAM%" == "--foo" (SHIFTIF 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" (SHIFTIF NOT "%ARG%" == "" (SET BAR=%ARG%SHIFT) ELSE (ECHO Missing bar value. 1>&2ECHO:GOTO usage)) ELSE IF "%PARAM%" == "--baz" (SHIFTSET BAZ=true) ELSE IF "%PARAM%" == "" (GOTO endargs) ELSE (ECHO Unrecognized option %1. 1>&2ECHO: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 BAZGOTO :eof
:usageECHO FooBarECHO 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%" == "--"
  • 当您使用其中一个参数时,请注意仅SHIFT
  • 重复的代码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。
  • 想要在Windows批处理文件中使用空白行?您必须使用ECHO:或其中一个变体。

简单的解决方案(即使问题很老)

Test1.bat

echo offecho "Batch started"set arg1=%1echo "arg1 is %arg1%"echo onpause

CallTest1.bat

call "C:\Temp\Test1.bat" pass123

输出

YourLocalPath>call "C:\Temp\test.bat" pass123
YourLocalPath>echo off"Batch started""arg1 is pass123"
YourLocalPath>pausePress any key to continue . . .

其中YourLocalPath是当前目录路径。

为了简单起见,将命令参数存储在变量中并使用变量进行比较。

它不仅写起来简单,而且维护起来也很简单,所以如果以后有人或你在很长一段时间后阅读你的脚本,它将很容易理解和维护。

要内联编写代码:请参阅其他答案。

输入图片描述

为了使用循环获取所有参数并在纯批处理中:

观察:不使用:#0


@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]!)
goto :eof

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

 @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 

在批处理文件

set argument1=%1set argument2=%2echo %argument1%echo %argument2%

%1%2分别返回第一个和第二个参数值。

在命令行中,传递参数

Directory> batchFileName admin P@55w0rd

输出将是

adminP@55w0rd

配对论点

如果你更喜欢在键值对中传递参数,你可以使用这样的东西:

@echo off
setlocal enableDelayedExpansion
:::::  asigning arguments as a key-value pairs:::::::::::::set counter=0for %%# in (%*) do (set /a counter=counter+1set /a even=counter%%2    
if !even! == 0 (echo setting !prev! to %%#set "!prev!=%%~#")set "prev=%%~#")::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: showing the assignmentsecho %one% %two% %three% %four% %five%
endlocal

举个例子:

c:>argumentsDemo.bat one 1 "two" 2 three 3 four 4 "five" 51 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.bat12

列出值的文件

您还可以指向预设所需值的文件。如果这是脚本:

@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

调用它的输出将是:

值1值2别的东西

当然,您可以将所有方法组合在一起。请选中参数语法转变

每个人都用非常复杂的回答来回答,但它实际上非常简单。%1 %2 %3等是解析到文件的论证。%1是论证1,%2是论证2,依此类推。

所以,如果我有一个包含以下内容的BAT脚本:

@echo offecho %1

当我运行批处理脚本时,我输入:

C:> script.bat Hello

脚本将简单地输出:

Hello

这对于脚本中的某些变量非常有用,例如姓名和年龄。所以,如果我有这样的脚本:

@echo offecho Your name is: %1echo Your age is: %2

当我输入这个:

C:> script.bat Oliver 1000

我得到这样的输出:

Your name is: OliverYour age is: 1000

如果你担心安全/密码被盗(这导致你设计了这个解决方案,在执行时获取登录凭据,而不是静态硬编码,而不需要数据库),那么你可以将api或密码解密或解密密钥的一半代码存储在程序文件中,所以在运行时,用户将在控制台中键入用户名/密码进行哈希/解密,然后通过set /p传递给程序代码执行,如果你在运行时查看用户输入凭据。

如果您正在运行脚本以使用各种用户/密码运行您的程序,那么命令行参数将适合您。

如果您正在制作一个测试文件来查看不同登录的输出/效果,那么您可以将所有登录存储在一个加密文件中,作为arg传递给test.cmd,除非您想坐在命令行并键入所有登录直到完成。

可以提供的参数数为仅限于命令行上的总字符。为了克服这个限制,上一段技巧是一种解决方法,而不会冒暴露用户密码的风险。