如何检查“.bat”文件中的命令行参数?
Posted
技术标签:
【中文标题】如何检查“.bat”文件中的命令行参数?【英文标题】:How to check command line parameter in ".bat" file? 【发布时间】:2011-06-24 14:26:15 【问题描述】:我的操作系统是 Windows Vista。我需要有一个“.bat”文件,我需要在其中检查用户是否输入了任何命令行参数。如果是,那么如果参数等于-b
,那么我会做一些事情,否则我会标记“无效输入”。如果用户没有输入任何命令行参数,那么我会做一些事情。我创建了以下 .bat 文件。它适用于 -b
和不等于 -b
的情况 - 但当用户不传递任何命令行参数时它会失败。
我总是出错:
GOTO was unexpected at this time.
谁能告诉我我在这里做错了什么?
ECHO OFF
CLS
ECHO.
IF [%1]==[/?] GOTO BLANK
IF %1=="-b" GOTO SPECIFIC
IF NOT %1=="-b" GOTO UNKNOWN
:SPECIFIC
ECHO SPECIFIC
GOTO DONE
:BLANK
ECHO No Parameter
GOTO DONE
:UNKNOWN
ECHO Unknown Option
GOTO DONE
:DONE
ECHO Done!
【问题讨论】:
如果在另外两个IF
语句中添加括号(如在GOTO BLANK
行中),是否可以解决问题?
【参考方案1】:
需要检查参数是否为空:if "%~1"=="" goto blank
完成此操作后,请在 -b 上执行 if/else 开关:if "%~1"=="-b" (goto specific) else goto unknown
用引号将参数括起来可以更轻松地检查诸如空白/空/缺失参数之类的内容。 "~" 确保双引号在命令行参数上时被去除。
【讨论】:
这行得通!只有“else”不被接受。我收到错误:“else”不被识别为内部或外部命令、可运行程序或批处理文件。所以我为“不等于-b”的情况添加了另一个IF。感谢您的快速回答。 ELSE 必须和 IF 在同一行,或者直接在括号之后 如果 %1 包含空格,这似乎对我不起作用,如果它是可执行文件的完整路径,可能就是这种情况。请参阅 Jeremiah Willcock's answer 以获取即使对于值中包含空格的参数也有效的解决方案。 如果您的论点是File
,它将不会被接受,在这种情况下,您应该只检查exist
或not exist
。这就是为什么你的论点应该定义明确,或者简单地使用 powershell 或 vbScript(如果你是 80 年代......)
run.bat "a b"
失败。如果 arg 有空格,"%1"==""
会崩溃。见***.com/a/46942471【参考方案2】:
查看http://ss64.com/nt/if.html 以获得答案;命令是IF [%1]==[] GOTO NO_ARGUMENT
或类似的。
【讨论】:
这不仅有效!与"%1"==""
相比,它可以正常工作。我必须在自己的答案中详细说明。
这会在 %1 被引用时中断,例如foo.bat "1st parameter" 2nd_param
。见***.com/questions/2541767/…
如果引用了 arg,则使用 [%1]==[-b]
将不匹配。示例run.bat "-b"
。见***.com/a/46942471
即使引用了参数,这也对我有用。例如foo.bat "1st parameter" 在我的测试中运行良好。方括号似乎比 IF "%1"==""【参考方案3】:
您正在比较字符串。如果省略参数,%1
将扩展为空白,因此命令变为 IF =="-b" GOTO SPECIFIC
例如(这是语法错误)。将字符串用引号(或方括号)括起来。
REM this is ok
IF [%1]==[/?] GOTO BLANK
REM I'd recommend using quotes exclusively
IF "%1"=="-b" GOTO SPECIFIC
IF NOT "%1"=="-b" GOTO UNKNOWN
【讨论】:
如果 [%1]==[/?] 不工作,但如果我做 IF [%1]==[] 或 "%1"=="",那么它工作。无论如何,现在我可以开始了。感谢您的快速回复。【参考方案4】:除了我订阅的其他答案,您可以考虑使用IF
命令的/I
开关。
... /I 开关(如果指定)表示进行不区分大小写的字符串比较。
如果您想为用户提供不区分大小写的灵活性来指定参数,这可能会有所帮助。
IF /I "%1"=="-b" GOTO SPECIFIC
【讨论】:
【参考方案5】:简短的回答 - 使用方括号:
if [%1]==[] goto :blank
或(当您需要处理带引号的参数时,请参阅下面的编辑):
if [%~1]==[] goto :blank
为什么?你可能会问。好吧,正如 Jeremiah Willcock 提到的:http://ss64.com/nt/if.html - 他们使用它!好的,但是引号有什么问题?
再次,简短的回答:它们是“神奇的” - 有时双(双)引号会转换为单(双)引号。首先,它们需要匹配。
考虑一下这个小脚本:
@rem argq.bat
@echo off
:loop
if "%1"=="" goto :done
echo %1
shift
goto :loop
:done
echo Done.
让我们测试一下:
C:\> argq bla bla
bla
bla
Done.
似乎有效。但是现在,让我们切换到二档:
C:\> argq "bla bla"
bla""=="" was unexpected at this time.
Boom 这没有评估为真,也没有评估为假。剧本死了。如果你应该在某个地方关闭反应堆,那么 - 运气不好。你现在会像 Harry Daghlian 一样死去。
你可能会想——好吧,参数不能包含引号。如果他们这样做,就会发生这种情况。 错以下是一些安慰:
C:\> argq ""bla bla""
""bla
bla""
Done.
哦,是的。别担心 - 有时这会工作。
让我们尝试另一个脚本:
@rem args.bat
@echo off
:loop
if [%1]==[] goto :done
echo %1
shift
goto :loop
:done
echo Done.
您可以自己测试一下,它是否适用于上述情况。这是合乎逻辑的——引号与括号无关,所以这里没有魔法。但是用括号给 args 增添趣味呢?
D:\>args ]bla bla[
]bla
bla[
Done.
D:\>args [bla bla]
[bla
bla]
Done.
那里没有运气。方括号不能阻塞cmd.exe
的解析器。
让我们暂时回到邪恶的名言。 问题就在那里,当参数以引号结束时:
D:\>argq "bla1 bla2"
bla2""=="" was unexpected at this time.
如果我通过了怎么办:
D:\>argq bla2"
The syntax of the command is incorrect.
脚本根本不会运行。 args.bat
也一样:
D:\>args bla2"
The syntax of the command is incorrect.
但是,在这种情况下,当"
-characters “匹配”的数量(即 - 是偶数)时,我会得到什么:
D:\>args bla2" "bla3
bla2" "bla3
Done.
NICE - 我希望您了解.bat
文件如何拆分它们的命令行参数(提示:*这与 bash 中的不完全一样)。上面的参数包含一个空格。但引号不会自动剥离。
还有 argq?它对此有何反应?可想而知:
D:\>argq bla2" "bla3
"bla3"=="" was unexpected at this time.
所以 - 在你说:“知道吗?只需使用引号。[因为,对我来说,这看起来更好]”。
编辑
最近,有一些关于这个答案的 cmets - 好吧,方括号“无法处理”传递引用的参数并将它们视为没有被引用。
语法:
if "%~1"=="" (...)
这不是双引号的一些新发现的优点,而是显示从参数变量中去除引号的简洁功能,如果第一个和最后一个字符是双引号。
这种“技术”与方括号一样有效:
if [%~1]==[] (...)
指出这一点很有用,所以我也赞成新的答案。
最后,双引号的粉丝们,您的书中是否存在""
形式的参数,还是空白?只是问问;)
【讨论】:
如果 arg 像run.bat "-b"
一样被引用,方括号 [%1]==[-b]
将不匹配。见***.com/a/46942471
历史记录:[%1]==[-b]
和 "%1"=="-b"
对于 win 98 和更早的 MS/PC-DOS 系统批处理脚本是相同的。由于 win 2000/NT 引入了语法if "%~1"=="-b"
,其中双引号具有特殊含义,这是您应该编写脚本的方式,因为它提供了更强大的保护。双引号会转义特殊字符的含义(在命令行中尝试 & | 和 % 字符)。 99.9% 的示例使用双引号语法 - 您的示例 argq bla2" "bla3
仅用于证明方括号的合理性。嵌入的双引号是灾难的秘诀 - 只是说'
@SkipR - 这就是为什么在 Windows 的文件系统中,您不能在名称中包含这些特殊字符。我没有数学证明,但我认为在cmd
shell 中根本不能引用所有内容(在 - 通过一些转义序列等逐字逐句的意义上)。在其他系统中,您有时可以引用所有内容,包括 NUL 字符。 (***.com/questions/2730732/…) - 这个问题只是显示,你需要使用一些外部程序。【参考方案6】:
实际上,所有其他答案都有缺陷。最可靠的方法是:
IF "%~1"=="-b" (GOTO SPECIFIC) ELSE (GOTO UNKNOWN)
详细说明:
如果使用空格和引号传递参数,使用"%1"=="-b"
将彻底崩溃。这是最不可靠的方法。
IF "%1"=="-b" (GOTO SPECIFIC) ELSE (GOTO UNKNOWN)
C:\> run.bat "a b"
b""=="-b" was unexpected at this time.
使用[%1]==[-b]
更好,因为它不会因空格和引号而崩溃,但如果参数被引号包围,它将不匹配。
IF [%1]==[-b] (GOTO SPECIFIC) ELSE (GOTO UNKNOWN)
C:\> run.bat "-b"
(does not match, and jumps to UNKNOWN instead of SPECIFIC)
使用"%~1"=="-b"
是最可靠的。 %~1
将去掉周围的引号(如果存在)。所以它可以带引号和不带引号,也可以不带参数。
IF "%~1"=="-b" (GOTO SPECIFIC) ELSE (GOTO UNKNOWN)
C:\> run.bat
C:\> run.bat -b
C:\> run.bat "-b"
C:\> run.bat "a b"
(all of the above tests work correctly)
【讨论】:
这不是方括号的结尾,你看:IF [%~1]==[]
- 这有效,它甚至可以处理"-b"
。您只需要能够在框、erm、方[括号]中思考。【参考方案7】:
我最近一直在努力在批处理文件中实现复杂的参数切换,所以这是我的研究结果。所提供的答案都不是完全安全的,例如:
"%1"=="-?"
如果参数包含在引号中(文件名等需要)将不匹配,或者如果参数包含在引号中并且包含空格(在文件名中也经常出现),则"%1"=="-?"
将崩溃
@ECHO OFF
SETLOCAL
echo.
echo starting parameter test...
echo.
rem echo First parameter is %1
if "%1"=="-?" (echo Condition is true, param=%1) else (echo Condition is false, param=%1)
C:\>test.bat -?
starting parameter test...
Condition is true, param=-?
C:\>test.bat "-?"
starting parameter test...
Condition is false, param="-?"
如果参数在引号中包含空格,则任何与方括号 [%1]==[-?]
或 [%~1]==[-?]
的组合都会失败:
@ECHO OFF
SETLOCAL
echo.
echo starting parameter test...
echo.
echo First parameter is %1
if [%~1]==[-?] (echo Condition is true, param=%1) else (echo Condition is false, param=%1)
C:\>test.bat "long file name"
starting parameter test...
First parameter is "long file name"
file was unexpected at this time.
建议的最安全的解决方案"%~1"=="-?"
将因包含引号外的文本和引号内的空格的复杂参数而崩溃:
@ECHO OFF
SETLOCAL
echo.
echo starting parameter test...
echo.
echo First parameter is %1
if "%~1"=="-?" (echo Condition is true, param=%1) else (echo Condition is false, param=%1)
C:\>test.bat -source:"long file name"
starting parameter test...
First parameter is -source:"long file name"
file was unexpected at this time.
确保涵盖所有上述情况的唯一方法是使用EnableDelayedExpansion 并使用变量通过引用(而不是通过值)传递参数。那么即使是最复杂的场景也能正常工作:
@ECHO OFF
SETLOCAL EnableDelayedExpansion
echo.
echo starting parameter test...
echo.
echo First parameter is %1
:: we assign the parameter to a variable to pass by reference with delayed expansion
set "var1=%~1"
echo var1 is !var1!
:: we assign the value to compare with to a second variable to pass by reference with delayed expansion
set "var2=-source:"c:\app images"\image.png"
echo var2 is !var2!
if "!var1!"=="!var2!" (echo Condition is true, param=!var1!) else (echo Condition is false, param=!var1!)
C:\>test.bat -source:"c:\app images"\image.png
starting parameter test...
First parameter is -source:"c:\app images"\image.png
var1 is -source:"c:\app images"\image.png
var2 is -source:"c:\app images"\image.png
Condition is true, param=-source:"c:\app images"\image.png
C:\>test.bat -source:"c:\app images"\image1.png
starting parameter test...
First parameter is -source:"c:\app images"\image1.png
var1 is -source:"c:\app images"\image1.png
var2 is -source:"c:\app images"\image.png
Condition is false, param=-source:"c:\app images"\image1.png
C:\>test.bat -source:"c:\app images\image.png"
starting parameter test...
First parameter is -source:"c:\app images\image.png"
var1 is -source:"c:\app images\image.png"
var2 is -source:"c:\app images"\image.png
Condition is false, param=-source:"c:\app images\image.png"
【讨论】:
以上是关于如何检查“.bat”文件中的命令行参数?的主要内容,如果未能解决你的问题,请参考以下文章