如何在启动/调用批处理文件时检查是不是定义了参数?
Posted
技术标签:
【中文标题】如何在启动/调用批处理文件时检查是不是定义了参数?【英文标题】:How can I check if an argument is defined when starting/calling a batch file?如何在启动/调用批处理文件时检查是否定义了参数? 【发布时间】:2010-10-24 06:04:49 【问题描述】:我正在尝试在批处理文件中使用以下验证逻辑,但即使未向批处理文件提供参数,“使用”块也不会执行。
if ("%1"=="") goto usage
@echo This should not execute
@echo Done.
goto :eof
:usage
@echo Usage: %0 <EnvironmentName>
exit 1
我做错了什么?
【问题讨论】:
What is the proper way to test if a parameter is empty in a batch file?的可能重复 @double-beep - 这里的问题(由 daniel-fortunov 提出)是在您提到的问题发布前大约一年提出的。哪个是(可能的)重复项? @KevinFegan 因为另一个问题有更多的观点和更多的答案。 【参考方案1】:检查是否设置了命令行参数可以是[%1]==[]
,但是Dave Costapoints out,"%1"==""
也可以。
我还修复了用法回显中的语法错误以转义大于和小于符号。此外,exit
需要一个 /B
参数,否则 CMD.exe
将退出。
@echo off
if [%1]==[] goto usage
@echo This should not execute
@echo Done.
goto :eof
:usage
@echo Usage: %0 ^<EnvironmentName^>
exit /B 1
【讨论】:
[%1]==[] 优于 "%1"=="" 因为它可以正确处理 %1 本身包含双引号的情况。 “%1”=="" 将出错并显示“此时意外”消息。 请注意,如果您使用的不是命令行参数而是set
变量(我不知道正确的批处理术语),您可能需要使用"%myvar%"==""
,因为如果myvar
有里面有空格并且没有被引用,你会得到“unexpected at this time”的信息。
@Pat SET 变量可以用IF NOT DEFINED VarName
块检查。还 +1 对 tukushan 比较不使用引号。只是不要这样做。从不。
"%~1"==""
也可以工作并处理 %1 有双引号的情况
"%~1"==""
处理变量中的空格,而 []
版本不处理。【参考方案2】:
@echo 关闭 :环形 ::---------------------------- 有论据? 如果 ["%~1"]==[""] ( 回声完成。 转到结束 ) ::---------------------------- 参数存在吗? 如果不存在 %~s1 ( 回声不存在 ) 别的 ( 回声存在 如果存在 %~s1\NUL ( echo 是一个目录 ) 别的 ( 回声是一个文件 ) ) ::---------------------------- 转移 转到循环 :结尾 暂停一个更高级的例子:
⍟ 无限参数。
⍟ 存在于文件系统上(
file
或directory
?)或通用的string
。⍟指定是否为文件
⍟指定是一个目录
⍟ no 扩展,可以在旧脚本中使用!
⍟ 最小代码☺
✨其他的东西..✨
■ 在 %~1
中 - ~
删除任何包装 "
或 '
。
■ 在%~s1
- s
使路径成为DOS 8.3 naming
,这是在检查内容时避免文件名中的空格的好方法(这样就不需要用更多@987654333 包装资源@s.
■ ["%~1"]==[""]
“不能确定”参数是文件/目录还是只是一个通用字符串,所以表达式使用括号和原始未修改的%1
(只是没有"
包装, 如果有的话..)
如果没有参数表明我们是否使用了shift
,并且 arg-list 指针已通过最后一个,则表达式将被评估为 [""]==[""]
。
■ 在不使用更多技巧的情况下,您可以做到尽可能具体(即使在 windows-95 的批处理脚本中也可以使用...)
■ 执行示例
另存为identifier.cmd
它可以识别无限的参数(通常你被限制为%1
-%9
),只要记住用引号括起来,或者使用 8.3 命名,或者拖放它们(它会自动执行以上)。
这允许您运行以下命令:
⓵identifier.cmd c:\windows
并得到
⓶identifier.cmd "c:\Program Files (x86)\Microsoft Office\OFFICE11\WINWORD.EXE"
并得到
⓷和多个参数(当然这是全部..)
identifier.cmd c:\windows\system32 c:\hiberfil.sys "c:\pagefile.sys" hello-world
得到
存在 是一个目录 存在 是一个文件 存在 是一个文件 不存在 完毕。自然会复杂得多, 但好的例子应该总是简单而最少的。 :)
希望它可以帮助任何人:)
在此发布:CMD Ninja - Unlimited Arguments Processing, Identifying If Exist In File-System, Identifying If File Or Directory
这是一个工作示例,它获取任意数量的 APK 文件(android 应用程序)并通过调试控制台 (ADB.exe) 将它们安装在您的设备上: Make The Previous Post A Mass APK Installer That Does Not Uses ADB Install-Multi Syntax
【讨论】:
【参考方案3】:去掉括号。
示例批处理文件:
echo "%1"
if ("%1"=="") echo match1
if "%1"=="" echo match2
运行上述脚本的输出:
C:\>echo ""
""
C:\>if ("" == "") echo match1
C:\>if "" == "" echo match2
match2
我认为它实际上将括号作为字符串的一部分,并且正在对它们进行比较。
【讨论】:
if "%1"==""
如果 arg 有空格会崩溃。例如:run.bat "a b"
。 @amr 有最好的答案来使用if "%~1"==""
【参考方案4】:
IF "%~1"=="" GOTO :Usage
~ 如果 %1 本身被引用,则将取消对 %1 的引用。
" " 将防止传递的特殊字符。例如用 &ping 调用脚本
【讨论】:
这是最好的答案。其他答案适用于某些情况,但对于更多特殊情况(如run.bat "a b"
)将失败
@wisbucky 这似乎并没有搞砸the accepted answer。我错过了什么?
@ruffin,例如:run.bat ""
不会被[%1]==[]
捕获。【参考方案5】:
这与其他答案相同,但仅使用一个标签并将用法放在首位,这也使其作为脚本的一种文档推荐,通常也位于顶部:
@echo off
:: add other test for the arguments here...
if not [%1]==[] goto main
:: --------------------------
echo This command does something.
echo.
echo %0 param%%1 param%%2
echo param%%1 the file to operate on
echo param%%1 another file
:: --------------------------
exit /B 1
:main
:: --------------------------
echo do something with all arguments (%%* == %*) here...
但是,如果您不必使用 cmd/batch,可以在 WSL 或 powershell 上使用 bash,它们的语法更健全,神秘功能更少。
【讨论】:
【参考方案6】:IF "%1"=="" GOTO :Continue
.....
.....
:Continue
IF "%1"=="" echo No Parameter given
【讨论】:
run.bat "a b"
崩溃【参考方案7】:
如果 "%1"=="" 将失败,则所有版本都将失败 某些毒字符条件。 只有 IF DEFINED 或 IF NOT DEFINED 才是安全的
【讨论】:
if [not] defined ...
不适用于%1
等参数。你有一个例子,if "%~1" ...
不起作用?
这是一个简单的代码注入示例。创建一个名为unsafe.bat
的文件,其内容为if "%~1"=="" ( echo hello )
。现在从 Powershell 运行以下.\unsafe.bat "_`" neq `"`" echo Pwned &::"
。还使用社区答案 ***.com/a/34552964/1490584 运行相同的 Powershell 参数。您会看到默认情况下批处理参数非常不安全以上是关于如何在启动/调用批处理文件时检查是不是定义了参数?的主要内容,如果未能解决你的问题,请参考以下文章
如何检查检查PInvoke签名的调用约定和参数与非托管的目标签名是不是匹配?
如何通过批处理文件检查服务是不是正在运行并启动它,如果它没有运行?