Batch file 是否有传递参数的方法;“按名称”;(而不是按订单)添加到batch.bat文件?

Batch file 是否有传递参数的方法;“按名称”;(而不是按订单)添加到batch.bat文件?,batch-file,Batch File,我需要能够通过名称(而不是顺序)向windows批处理文件传递参数。我在这里的目的是给最终用户以任意顺序传递参数的灵活性,批处理文件应该仍然能够处理它们 让我的问题更清楚的一个例子是: 在命令行中,用户执行以下操作: somebatchfile.bat originalFile.txt newFile.txt 在somebatchfile.bat内部,有一条简单的语句可以将原始文件(第一个参数%1%)的内容复制到新文件(第二个参数%2%)。它可以像以下语句一样简单: 复制%1%%2% 现在,如果

我需要能够通过名称(而不是顺序)向windows批处理文件传递参数。我在这里的目的是给最终用户以任意顺序传递参数的灵活性,批处理文件应该仍然能够处理它们

让我的问题更清楚的一个例子是:

在命令行中,用户执行以下操作:
somebatchfile.bat originalFile.txt newFile.txt

somebatchfile.bat内部,有一条简单的语句可以将原始文件(第一个参数%1%)的内容复制到新文件(第二个参数%2%)。它可以像以下语句一样简单:
复制%1%%2%

现在,如果用户以相反的顺序传递上述参数,结果将远远不理想(事实上是非常错误的)

那么,有没有一种方法可以让用户按名称传递参数:例如,
somebatchfile.bat“SOURC=originalFile.txt”“TARGET=newFile.txt”
,让脚本识别它们并在正确的位置使用它们,例如,
copy%SOURCE%%TARGET%


谢谢,

是的,你可以这样做,尽管我认为你不能用“=”作为标记分隔符。您可以使用冒号“:”,
somebatchfile.bat“SOURC:originalFile.txt”“TARGET:newFile.txt”
。下面是一个如何拆分令牌的示例:

@echo off

set foo=%1
echo input: %foo%

for /f "tokens=1,2 delims=:" %%a in ("%foo%") do set name=%%a & set val=%%b

echo name:  %name%
echo value: %val%
运行此命令将产生以下结果:

C:\>test.bat SOURC:originalFile.txt
input: SOURC:originalFile.txt
name:  SOURC
value: originalFile.txt
[编辑]

好吧,也许昨晚我离睡觉时间太近了,但今天早上再看一遍,你可以这样做:

@echo off

set %1
set %2

echo source: %SOURCE%
echo target: %TARGET%
这将产生以下结果(请注意,我在命令行上反转了源和目标,以显示它们已正确设置和检索):


请注意,在设置
之前对%1和%2进行求值,因此它们确实被设置为环境变量。但是,必须在命令行中引用它们。

我认为您正在寻找Windows批处理脚本中的getopt支持,不幸的是,这些脚本并不完整。最接近你可能得到的是使用。这样,您就可以使用以下命令执行脚本:

somebatchfile.bat /SOURC:originalFile.txt /TARGET:newFile.txt
arguments.bat -c users -u products
代码:


我想看看读取提供给批处理程序的命名参数的可能性。例如:

myBatch.bat arg1  arg2 
读取参数的步骤如下:

%~1 would be arg1
%~2 would be arg2
上面提供给批处理程序的参数很容易阅读,但每次执行它时,您都必须保持顺序并记住arg1应该有什么。为了克服这个问题,参数可以作为key:value格式提供。命令如下所示:

mybatch.bar key1:value1 key2:value2
虽然没有直接的方法来解析这样的参数列表。我在批处理脚本中编写了以下嵌套for循环,它将基本上解析和创建以key1为名称的环境变量,并为其分配value1。通过这种方式,您可以读取使用直接读取环境变量的方式提供的所有参数

@echo off
FOR %%A IN (%*) DO (
   FOR /f "tokens=1,2 delims=:" %%G IN ("%%A") DO setLocal %%G=%%H
)
之后,您可以使用
%key1%
格式读取提供的所有参数


HTH

另一方面,我非常喜欢:

set c=defaultC
set s=defaultS
set u=defaultU

:initial
if "%1"=="" goto done
echo              %1
set aux=%1
if "%aux:~0,1%"=="-" (
   set nome=%aux:~1,250%
) else (
   set "%nome%=%1"
   set nome=
)
shift
goto initial
:done

echo %c%
echo %s%
echo %u%
运行以下命令:

somebatchfile.bat /SOURC:originalFile.txt /TARGET:newFile.txt
arguments.bat -c users -u products
将生成以下输出:

users
defaultS
products
此代码检查所有参数,去掉所有外部引号,如果存在等号,则将变量设置为值

像这样使用它:

yourbatch.bat "foo=bar" "foo2=bar2"
基于此答案:,并针对该方晚了一点的编辑尝试进行了编辑:)这是我对管理“类似posix”选项的建议。 例如
mybatchscript.bat-foo=foovalue-bar=barvalue-flag

:parseArgs
:: asks for the -foo argument and store the value in the variable FOO
call:getArgWithValue "-foo" "FOO" "%~1" "%~2" && shift && shift && goto :parseArgs

:: asks for the -bar argument and store the value in the variable BAR
call:getArgWithValue "-bar" "BAR" "%~1" "%~2" && shift && shift && goto :parseArgs

:: asks for the -flag argument. If exist set the variable FLAG to "TRUE"
call:getArgFlag "-flag" "FLAG" "%~1" && shift && goto :parseArgs


:: your code here ...
echo FOO: %FOO%
echo BAR: %BAR%
echo FLAG: %FLAG%

goto:eof
…这里是完成这项工作的功能。您应该将它们放在同一批处理文件中

:: =====================================================================
:: This function sets a variable from a cli arg with value
:: 1 cli argument name
:: 2 variable name
:: 3 current Argument Name
:: 4 current Argument Value
:getArgWithValue
if "%~3"=="%~1" (
  if "%~4"=="" (
    REM unset the variable if value is not provided
    set "%~2="
    exit /B 1
  )
  set "%~2=%~4"
  exit /B 0
)
exit /B 1
goto:eof



:: =====================================================================
:: This function sets a variable to value "TRUE" from a cli "flag" argument
:: 1 cli argument name
:: 2 variable name
:: 3 current Argument Name
:getArgFlag
if "%~3"=="%~1" (
  set "%~2=TRUE"
  exit /B 0
)
exit /B 1
goto:eof
将文件另存为
mybatchscript.bat
并运行

mybatchscript.bat -bar=barvalue -foo=foovalue -flag
您将获得:

FOO: foovalue
BAR: barvalue
FLAG: TRUE

非常老的问题,但我认为我找到了一种将
key=value
参数传递到批处理文件的简洁方法(没有外部依赖关系)。您可以使用以下MWE测试该方法:

@echo off
chcp 65001

rem name this file test.bat and call it with something like:
rem test keyc=foo keyd=bar whatever keya=123 keyf=zzz

setlocal enabledelayedexpansion

set "map=%*"
call :gettoken keya var1
call :gettoken keyb var2
call :gettoken keyc var3

rem replace the following block with your real batch
rem ************************************************
echo:
echo Map is "%map%"
echo Variable var1 is "%var1%"
echo Variable var2 is "%var2%"
echo Variable var3 is "%var3%"
echo:
echo Done.
echo:
pause
rem ************************************************

goto :eof
:gettoken
call set "tmpvar=%%map:*%1=%%"
if "%tmpvar%"=="%map%" (set "%~2=") else (
for /f "tokens=1 delims= " %%a in ("%tmpvar%") do set tmpvar=%%a
set "%~2=!tmpvar:~1!"
)
exit /b
方法非常简单:

  • 灵活,因为
    key=value
    参数可以与其他参数(例如文件名)混合,并且用于存储值的变量的名称独立于键的名称
  • 可扩展,因为很容易添加密钥
  • 健壮,因为忽略已定义的键不允许传递的任何内容,而未分配的键会得到一个空值(如果需要,您可以轻松更改此行为,使它们得到类似于
    null
    未定义的值,而不是空值)
享受。

尝试一下(纯批量):

以及一些测试:

call args.bat /bar="Hello World" Test1 -baz "Test test test" /foo=Test1 Test2

echo foo=%ARG_foo%
echo bar=%ARG_bar%
echo baz=%ARG_baz%
echo count=%PARAM_0%
echo 1=%PARAM_1%
echo 2=%PARAM_2%
产出:

foo="Test1"
bar="Hello World"
baz="Test test test"
count=2
1="Test1"
2="Test2"
我的天哪,我的人民;你想得太多了!:) OP的
CMD
arg的格式都是
“[VarName]=[Something]”

所以第一行可以是%%\uIn(%%*)DO SET“%%~\u”
或者用好看的代码

对于(%*)中的%%\u,请设置“%%~\u”
也就是说,这里有一个更完整的脚本示例,您可以将所有脚本放在
:Main
函数中

@(Setlocal)
回音
对于(%*)中的%%\u,请设置“%%~\u”
)
电话:Main
(完)
退出(B)
:Main
你的代码在这里。
你的代码在这里。
你的代码在这里。
你的代码在这里。
后藤:EOF

谢谢Dave,但您的解决方案涉及批处理文件内部的“相当多的处理”。然而,我们需要的是一种“内置”功能,它可以自动使用传递的参数填充内部变量(在用户脚本中)。例如:按照惯例,他们知道如果他们传递这样一个参数:“SOURC:originalFile.txt”,那么他们的内部变量%name%和%val%将自动获得正确的值。@Pouya:此批处理脚本仅用一行代码解析
name&value
对。这怎么可能是相当多的处理呢?但是,我看到你说的是拥有内置功能——不,批处理脚本是一个非常有限的工具,微软(再次)通过引入PowerShell间接承认了这一点
call args.bat /bar="Hello World" Test1 -baz "Test test test" /foo=Test1 Test2

echo foo=%ARG_foo%
echo bar=%ARG_bar%
echo baz=%ARG_baz%
echo count=%PARAM_0%
echo 1=%PARAM_1%
echo 2=%PARAM_2%
foo="Test1"
bar="Hello World"
baz="Test test test"
count=2
1="Test1"
2="Test2"