执行CMD命令的两种方式分别是手动创建一个Cmd窗口和执行bat批处理文件。
第一种,先手动创建一个cmd窗口,然后往里面输入cmd命令,最后回车执行。
第二种,先在一个bat文件中键入cmd命令,保存代码后,双击执行。
第三种,先在一个bat文件中键入cmd命令,保存代码后,在手动创建的cmd窗口中用命令执行bat文件。
何谓批处理命令中的参数?
在手动创建的Cmd窗口中直接执行命令是没有参数可言的,只有在手动创建的cmd窗口中执行bat批处理文件才有参数。
因为%0-%9都是形式参数,如果没有赋值,就是普通字符串,所以下面在手动创建的cmd窗口中echo出来的都是原文本。如果把%0-%9比作10个指针,当没有指向一个数值时,就是普通字符串。
往bat文件中输入参数的格式如下:bat_filepath arg1 arg2 ... argx(bat_filepath表示第0个参数,对应%0,arg1表示第x个参数,对应%1,以此类推,参数与参数之间用空格或制表符分隔)。
假设 【d:\D-desktop】中有3个bat文件——main.bat、main1.bat、demo.bat。
demo.bat文件中的代码如下:
chcp 65001
@echo off
echo %0
echo %~0
echo %~f0
echo %1
echo %2
pause
在当前目录为【d:\D-desktop】的情况下,执行命令【demo main.bat main1.bat】。
结果如下,我们可以看到五行输出中,demo对应%0,于是echo %0的输出是demo,而main.bat对应%1、main1.bat对应%2,于是echo %1和echo %2的输出是main.bat和main1.bat。
至于第2行的echo %~0和第3行的echo %~f0,涉及到参数扩展的知识,我们在第五章详细铺开。
那什么是%*呢?
%*代表全部的批处理参数,也即代表%1-%9整体,不同参数之间用空格分隔。
在main.bat文件中添加下面的代码,在cmd命令窗口执行命令【main.bat 123 456】。
@echo off
chcp 65001
echo %0
echo %1
echo %2
echo %*
pause
输出结果如下。
在bat脚本中直接执行【%0】或通过call命令调用%0,都会导致Bat文件陷入没有尽头的死循环。
@echo off
chcp 65001
echo "大哥出生了"&echo "二弟出生啦"&echo "三妹出生啦"
(
echo "大哥出生了"
echo "二弟出生啦"
echo "三妹出生啦"
)
call %0
pause
你们可以把上面这块代码复制到bat文件中,双击执行试试,绝对会不断地“生孩子”哈哈哈。
在本文第一章提到对cmd命令的3种执行方式(小生不才,可能还有更多种执行方式哈哈哈,但是本文只讨论这3种)。
第一种属于非批处理脚本执行方式,没有参数可言。
第二种和第三种属于批处理脚本执行方式。
第二种无法手动输入参数,但是有参数的意义,一般来说只有%0这一个参数,默认就是bat文件的完整路径。
但是,有些BAT文件中如果执行call命令的时候,不管是内部调用还是外部调用,只要后面加了参数,就至少给指针%1赋予了数据。
举个例子。
main.bat的代码(type %1下面还有一个空行,不然最后执行时第2个echo=的空行效果会被抑制)如下所示:
@echo off
echo %0
echo %~f0
echo=
call :end D:\D-desktop\demo.bat
pause
:end
type %~f0
echo=
type %1
demo.bat的代码(echo %2下面还有一个空行,不然最后type完了,主程序的pause提示信息会接在echo %2上)如下所示:
chcp 65001
@echo off
echo %0
echo %~0
echo %~f0
echo %1
echo %2
双击执行main.bat文件,结果如下所示:
我们可以发现demo.bat文件的路径参数被传至了主程序的%1中,也由此可见call命令进行内部调用时,批处理参数从%1开始计量。
第三种可以手动输入参数,与第二种执行方式不同的是%0这个参数根据执行bat文件时所用命令的输入形式有关,其中第1个输入值直接原本不动地转化为%0,可能会覆盖默认的完整路径。
举个例子,demo.bat文件在路径【D:\D-desktop】中。假设执行cmd命令【demo.bat】,那么%0就等于【demo.bat】。而如果是直接双击(也可以是其他非cmd命令执行方式),那么%0就是等于【D:\D-desktop\demo.bat】。
第二章我们知道形式参数一共有10个,分别是%0、%1、...、%9,但是实际我们可能会需要输入大于10的参数数量,如何实现呢?
这就要提到本章节的主人翁——shift命令。
执行【shift /?】。
一句话,shift命令专门用来偏移批处理参数和输入参数值之间的对应关系。
帮助文档对shift命令的简述是“更改批处理文件中可替换参数的位置” ,显然没有我的总结更加准确直观。
而shift命令的唯一参数就是/n,n指的是起始偏移位置。例如n=2时,只有%x(x>=2)的指针才需要偏移。
假设初始状态下(如下引用块所示),cmd为bat脚本文件名,可以用%0引用。
cmd arg1 arg2 arg3 arg4 arg5 arg6 arg7 arg8 arg9 arg10
| | | | | | | | | | |%0 %1 %2 %3 %4 %5 %6 %7 %8 %9
经过1次shift后,cmd将无法被引用,因为没有一个指针指向它。
cmd arg1 arg2 arg3 arg4 arg5 arg6 arg7 arg8 arg9 arg10
| | | | | | | | | |
%0 %1 %2 %3 %4 %5 %6 %7 %8 %9
经过2次shift后,arg1也被废弃,%9指向为空,也没有意义。
cmd arg1 arg2 arg3 arg4 arg5 arg6 arg7 arg8 arg9 arg10
| | | | | | | | |
%0 %1 %2 %3 %4 %5 %6 %7 %8
假设初始状态下(如下引用块所示),cmd为bat脚本文件名,可以用%0引用。
cmd arg1 arg2 arg3 arg4 arg5 arg6 arg7 arg8 arg9 arg10
| | | | | | | | | | |%0 %1 %2 %3 %4 %5 %6 %7 %8 %9
执行一次shift /2,因为起始偏移位置设置成2,因此%0和%1都原地待命,%2-%9才需要向右偏移。这时候,arg2参数值成为了没有指针指向的对象。
cmd arg1 arg2 arg3 arg4 arg5 arg6 arg7 arg8 arg9 arg10
| | | | | | | | | | |%0 %1 %2 %3 %4 %5 %6 %7 %8 %9
再执行一次shift /2,arg2和arg3全没指针引用,%9指针也没有指向一个参数值。
cmd arg1 arg2 arg3 arg4 arg5 arg6 arg7 arg8 arg9 arg10
| | | | | | | | | | |%0 %1 %2 %3 %4 %5 %6 %7 %8
很有意思的一点,批处理参数的扩展帮助文本,竟然是靠执行【call /?】获得的,call命令和批处理参数关系真不一般。
d:\D-desktop>call /?
从批处理程序调用另一个批处理程序。
CALL [drive:][path]filename [batch-parameters]
batch-parameters 指定批处理程序所需的命令行信息。
如果命令扩展被启用,CALL 会如下改变:
CALL 命令现在将卷标当作 CALL 的目标接受。语法是:
CALL:label arguments
一个新的批文件上下文由指定的参数所创建,控制在卷标被指定
后传递到语句。你必须通过达到批脚本文件末两次来 "exit" 两次。
第一次读到文件末时,控制会回到 CALL 语句的紧后面。第二次
会退出批脚本。键入 GOTO /?,参看 GOTO :EOF 扩展的描述,
此描述允许你从一个批脚本返回。
另外,批脚本文本参数参照(%0、%1、等等)已如下改变:
批脚本里的 %* 指出所有的参数(如 %1 %2 %3 %4 %5 ...)
批参数(%n)的替代已被增强。你可以使用以下语法:
%~1 - 删除引号("),扩展 %1
%~f1 - 将 %1 扩展到一个完全合格的路径名
%~d1 - 仅将 %1 扩展到一个驱动器号
%~p1 - 仅将 %1 扩展到一个路径
%~n1 - 仅将 %1 扩展到一个文件名
%~x1 - 仅将 %1 扩展到一个文件扩展名
%~s1 - 扩展的路径只含有短名
%~a1 - 将 %1 扩展到文件属性
%~t1 - 将 %1 扩展到文件的日期/时间
%~z1 - 将 %1 扩展到文件的大小
%~$PATH:1 - 查找列在 PATH 环境变量的目录,并将 %1
扩展到找到的第一个完全合格的名称。如果
环境变量名未被定义,或者没有找到文件,
此修改符会扩展到空字符串
可以组合修改符来取得多重结果:
%~dp1 - 只将 %1 扩展到驱动器号和路径
%~nx1 - 只将 %1 扩展到文件名和扩展名
%~dp$PATH:1 - 在列在 PATH 环境变量中的目录里查找 %1,
并扩展到找到的第一个文件的驱动器号和路径。
%~ftza1 - 将 %1 扩展到类似 DIR 的输出行。
在上面的例子中,%1 和 PATH 可以被其他有效数值替换。
%~ 语法被一个有效参数号码终止。%~ 修定符不能跟 %*
使用
d:\D-desktop>
如果%0对应的值不被引号包括,那么就没有任何区别,但是如果被引号包围,用%~0就能去除引号。
下图是双击执行main.bat文件的结果。
d对应drive——驱动器
f对应filepath——文件路径(包括文件名)
p对应path——路径(不包括文件名)
n对应name——文件名
x对应Ext——扩展名
a对应attribute——属性
z对应siZe——大小
%~$PATH:1——查找列在 PATH 环境变量的目录,并将 %1扩展到找到的第一个完全合格的名称。如果环境变量名未被定义,或者没有找到文件,此修改符会扩展到空字符串。
从帮助信息很容易理解它的含义,但是当我双击执行结果正常、而用CMD命令执行结果却不正常时,我就迷糊又懵逼了。
详见本文的第六章,作为高难度部分,希望各位读者能和我一起想出这个问题的答案!
bat文件代码如下
chcp 65001
@echo off
echo %0
echo %~0
echo %~dp0
echo %~f0
echo %~fs0
echo %~n0
echo %~s0
echo %~a0
echo %~t0
echo %~$PATH:0
echo %~dp$PATH:0
pause
直接执行,结果如下图,不能说正常,只能说完全正常好吧???
在cmd窗口通过命令执行(除了bat文件名本身,没有赋予其他参数), 结果如下。明显最后的echo %~$PATH:0和echo %~dp$PATH:0的输出结果出现异端,非常诡异。
当bat文件代码如下所示
chcp 65001
@echo off
echo %0
echo %~0
echo %~f0
echo %1
echo %2
pause
不仅包括%0,还有%1和%2时, 直接双击执行bat文件,结果如下图
因为双击执行时除了%0其他的批处理参数都没有值,所以涉及到的参数全部输出ECHO is off。