赞
踩
cmd>file //cmd命令的输出结果重定向到file文件
cmd<file //file文件作为cmd命令的输入参数
cmd>nul //cmd命令的输出结果重定向到nul中,也即丢弃
(1)小于号<重定向的应用示例
对于sort命令,需要一个路径参数,路径参数指向的是一个文本文件,文本文件中的内容正是这个sort命令的输入内容。因此,可以用<重定向命令,命令【sort /r D:\D-desktop\tool.txt】和命令【sort /r < D:\D-desktop\tool.txt】的效果是一样的。
(2)大于号<重定向的应用示例
sort命令不会改变原txt文件的内容,只是输出的结果改变了而已,如果想要把已排序好的内容放在新的txt文件中,可以执行重定向命令【sort D:\D-desktop\tool.txt>D:\D-desktop\tool
_sorted.txt】。
cmd>>file //cmd命令的输出结果追加到file文件
cmd<<file //file文件作为cmd命令的输入参数追加进去
(1)什么是句柄?
句柄 | 句柄的数字代号 | 描述 |
STDIN | 0 | 键盘输入 |
STDOUT | 1 | 输出到命令提示符窗口(屏幕) |
STDERR | 2 | 错误输出到命令提示符窗口(屏幕) |
UNDEFINED | 3-9 | 由应用程序单独定义,各个工具特有 |
(2)指令的应用示例
cmd>file //cmd的输出重定向到file文件
cmd>>file //cmd的输出追加到file中,无则创建
cmd 1>file //把运行cmd的shell的标准输出重定向到file中,1代表标准输出
cmd>file 2>&1 //把cmd的输出重定向到file,同时把2(错误输出)重定向到1(标准输出)
注意如果写的是【2 > 1】,则会把1当成文件,把错误定向到1须使用&1
cmd>right.txt 2>error.txt //把cmd命令的正确输出信息重定向到right.txt,错误输出信息重定向到 error.txt
cmd 2>file //把错误输出定向到file中
cmd>>file 2>&1 //把错误和cmd输出追加到file中,cmd>>file,追加;2>&1,错误定向到
标准输出,标准输入又追加到file中,所以错误和cmd输出都追加到file
cmd 1>>file 2>&1 //可以把此命令等效于上一个命令
cmd<<END //cmd使用标准输入,直到遇到END则退出.END可为任意一个字符
理解:cmd使用默认的标准输入,运行,碰到END,则追加,但是标准输入输出
不能追加,于是出错退出.
cmd<&m //把文件描述符m作为cmd的输入
cmd>&m //把文件描述符m作为cmd的输出
cmd<&- //关闭标准输入.
(1)清除重定向(例如>)与追加重定向(例如>>)的区别
(2)清除重定向、追加重定向和句柄重定向的差异
a、句柄重定向的对象只能是0(标准输入——键鼠),1(标准输出——屏幕),2(错误标准输出——屏幕)。
例如,命令【echo 123>file 2>&1】可以把echo命令的输出重定向到file,同时把2(错误输出)重定向到1(标准输出)。注意不能使用2 > 1,因为这样会把1当成文件。
b、对于句柄0 1 2,不能使用追加重定向符(<<或>>),例如2>>&1是错的。
示例:cd /d d:\src&work.exe /o c:\result.txt // 先将当前工作目录切换到d:\src下,然后执行work.exe /o c:\result.txt命令。
作用:在bash中,在某条命令后面跟上
&
,用来将命令放在后台执行,避免其占用命令行。顺序执行多条命令,而不管命令是否执行成功。
虽然多个命令写在同一行,但不意味着这些命令的输出内容也是不同行的。
上面这张图本质和下图的命令一样。下图中用到了括号符(),这个符号的作用就是用来清晰地排版代码的,并非起于dos语法上的需要,省略也不会出错,加上也不会出错。
含义:顺序执行多条命令,当碰到执行出错的命令后将不执行后面的命令。
例:find "ok" c:\test.txt && echo 成功 // 如果找到了"ok"字样,就显示"成功",找不到就不显示。
注解:在linux系统中实现类似作用的shell符号是【;】,其次注意理解——第三条命令被执行到的前提是第一、二条命令都执行正确,而非第二条命令是否执行正确 。
管道命令能够将一个命令的执行结果经过筛选,只保留我们需要的信息。如 dir 命令会显示目录下所有文件夹和文件,可以使用管道命令| findstr "" 将dir的结果进行筛选,只保留需要的信息。
含义:“管道命令”,将第一条命令的结果作为第二条命令的参数来使用。
Usage:第一条命令 | 第二条命令 [| 第三条命令...]
表面上,find和findstr没有区别,如下图所示;实际上,findstr支持正则表达式,find不支持
所以平常使用findstr居多,但是find够简洁好用。
find命令的语法
- /V #显示所有未包含字符串的行
- /C #仅显示匹配字符串的行数
- /N #显示行号
- /I #搜索时忽略大小写
- 使用的格式为:find /i "abc" abc.txt #不区分大小写查找
findstr命令的语法
- /b #如果位于行的开头则匹配模式。
- /e #如果位于行的末尾则匹配模式。
- /l #使用文字搜索字符串。
- /r #使用搜索串作为常规表达式。Findstr 将所有元字符解释为常规表达式,除非使用了 /l。
- /s #在当前目录和所有子目录中搜索匹配的文件。
- /i #指定搜索不区分大小写。
- /x #打印完全匹配的行。
- /v #只打印不包含匹配的行。
- /n #在每个匹配的行之前打印行号。
- /m #如果文件包含匹配项,仅打印该文件名。
- /o #在每次匹配行之前打印查找偏移量。
- /p #跳过包含非可打印字符的文件。
- /offline #利用脱机属性设置处理文件。
- /f:file #从指定文件中读取文件列表。
- /c:string #使用指定的文本作为文字搜索字符串。
- /g:file #从指定文件得到搜索字符串。
- /d:dirlist #搜索以逗号分隔的目录列表。
- /a:ColorAttribute #使用两个十六进制数指定颜色属性。
- strings #指定要在 FileName中搜索的文本。
- [Drive:][Path] FileName [...] #[drive:]、[path]是可选的,如果省略,默认是查找当前目录,至少指定一个文件,可以同时指定多个,用空格分隔,另外文件名可以使用通配符,例如所有文本文件,就可以写成 *.txt 即可。
- /? #在命令提示符显示帮助。
含义:顺序执行多条命令,当碰到执行正确的命令后反而不执行后面的命令。
Usage:第一条命令 || 第二条命令 [|| 第三条命令...]
注意理解,第三条命令被执行到的前提是第一、二条命令中全部执行错误,而非第二条命令是否执行错误 。
应用示例1——模拟C语言中的if else语句,既有条件判断,又有多个分支。
模板命令【cmd1 && command1 || cmd2 && command2 || cmd3 && command3 ...】
这个模板的意义是如果最前面的cmd1命令执行正确,那么最终只执行command1 ,如果执行错误就可以执行cmd2,如果cmd2对了那么执行command2,如果cmd2错了就执行cmd3,往后不断反复。
应用示例2——执行某命令,如果正确就打印succeed,如果错误就打印failed。
正确的情况。
错误的情况。
圆括号经常出现在for语句和if语句中,还有一些特殊场合也用到它。
例①:for %%i in (语句1) do (语句2)
在这条语句中,语句1必须用括号对包围,而语句2的括号对则可视情况予以抛弃或保留。
如果语句2是单条语句或用&、& &、||等连接符号连接的多条语句,括号对可以抛弃。
如果语句2是有逻辑先后关系的多条语句集合,则建议保留括号对,并且多条语句必须断行书写。
例如:
- @echo off
- for %%i in (a b c) do echo %%i&echo --------
- pause
也可以改写为:
- @echo off
- for %%i in (a b c) do (
- echo %%i
- &echo --------
- )
- pause
例②:if 条件 (语句1) else (语句2)
如果没有else if部分和else部分,则语句1的括号对可有可无;如果有则语句1中的括号对必须保留。
此时,语句2中的括号对保留与否,和例①类似。
例如:
- @echo off
- if exist test.txt echo 当前目录下有test.txt
- pause
- @echo off
- if exist test.txt (echo 当前目录下有test.txt) else echo 当前目录下没有test.txt
- pause
- @echo off
- if exist test.txt (echo 当前目录下有test.txt) else (
- echo 当前目录下没有test.txt
- pause
- cls
- echo 即将创建test.txt文件
- cd.>test.txt&&echo 成功创建test.txt
- )
- pause
例③ :多个命令连成复合命令,既可以用&操作符,也可用小括号()包裹
看下面的代码,第二个家庭和第三个家庭的执行效果相同,因为他们的三个孩子都是在一条语句(专业术语叫复合语句)的指导下出生的,也称三胞胎。
- @echo off
- chcp 65001
- echo "第一个家庭"
- echo "大哥出生了"
- echo "二弟出生啦"
- echo "三妹出生啦"
- echo "第二个家庭"
- echo "大哥出生了"&echo "二弟出生啦"&echo "三妹出生啦"
- echo "第三个家庭"
- (
- echo "大哥出生了"
- echo "二弟出生啦"
- echo "三妹出生啦"
- )
- pause
像这种用&、&&、|、||操作符连接,或者用小括号()包裹的语句,统称复合语句;复合语句有时就需要用到延迟变量(扩展变量)的功能,使得后续调用的变量是最新值。
特定场合下使用括号对,不但可以使代码逻辑清晰,增强可读性,还可能会减少代码量。
比如用echo语句构造多行文本内容的时候。
- @echo off
- (
- echo 第一行
- echo 第二行
- echo 第三行
- )>test.txt
- start test.txt
如果不使用括号对的话,则需要使用如下代码。
- @echo off
- echo 第一行>test.txt
- echo 第二行>>test.txt
- echo 第三行>>test.txt
- start test.txt
上箭头符在本文第十部分也有讲解,只不过那里讲的是上箭头符^用于“转义”。
换行接续符常用在if语句中,通过将if语句的各部分分行写出,可读性和兼容性都得以增强。
- if condition1 (
- command1
- ) ^
- else if condition2 (
- command2
- ) ^
- else if condition3 (
- command3
- ) ^
- else (
- command4
- )
当然了,如果你基础够夯实,其实它在充当接续符本质上就是在对行尾的换行符进行转义,换行符变成了普通符号,可不就使下一行接续上一行了吗?
一般在它之后紧跟一条命令或一条语句,则此条(行)命令或语句本身在执行的时候不会显示在屏幕上。
常常用在批处理脚本上,特别是用在echo off命令上,首行使用命令【@echo off】。
因为bat文件执行的时候,不需要把每一行命令都在cmd窗口上显示后再执行,这样会影响观感;更具美感的方式是将执行的命令和输出的结果放在不同的地方。
引号常常用来避免路径上的空格问题。
在绝对路径上加局部引号括起来,【D:\"Program Files"\python\Python38】
在绝对路径上加全局引号括起来,【D:\"Program Files\python\Python38"】
在相对路径上加全局引号括起来,【"Program Files"\python\Python38】
在相对路径上加全局引号括起来,【"Program Files\python\Python38"】
当in后面跟一个字符串时,用双引号括起来
- @echo off
- for /f "delims=. tokens=1-3" %%i in ("www.baidu.com") do echo %%i-%%j-%%k
- pause>nul
for命令参数/f,如果文件名不带空格,可以用
for /f %%i in (文件名) do (……)
但是文件名中有空格,为了避免路径空格问题,或者文件名中有类似&的特殊字符时,必须加双引号括起来;又因为与字符串情形冲突,必须加一个增强参数usebackq
for /f "usebackq" %%i in ("文件名") do (……)
find命令语句的string字段必须带双引号,如果string字段中本身就有双引号,就需要在内部用双引号括起来。
比如在report.doc文本文件中查找包括【abc"def"gh】的行,就需要把string字段写成【"abc""def""gh"】。
find "abc""def""gh" report.doc
当不添加后备规则参数usebackq,并且in后面跟一串命令时,用单引号括起来。
FOR /F ["options"] %variable IN ('command') DO command [command-parameters]
当添加后备规则参数usebackq,并且in后面跟一字符串时,用单引号括起来。
FOR /F "usebackq [other_options]" %variable IN ('string') DO command [command-parameters]
在 set /a 语句中,这些符号的含义分别为:加、减、乘、除。
例如:set /a num=1+2-3*4/5。
需要注意的是,这些运算符号遵循数学运算中的优先级顺序:先乘除后加减,有括号的先算括号,并且,直接忽略小数点,因此,刚才那个算式的结果是1而不是0或0.6。
另外,有可能会在代码中看到这样的写法。
set /a num+=1
set /a num-=1
set /a num*=1
set /a num/=1
这些表示累加、累减、累乘、累除,步长都是1,展开后的完整写法。
set /a num=num+1
set /a num=num-1
set /a num=num*1
set /a num=num/1
set /a 语句中,变量引用可以忽略百分号对或感叹号对,set /a num=%num%+1 与 set /a num=num+1 等同。
一般用在搜索上,比如where命令的pattern,支持通配符。
但是不能用在路径上,比如在指定路径【D:\Program Files\python\Python38】时,我们不能用【D:\Program?Files\python\Python38】来避免“路径空格问题”。
dir命令也支持通配符
【dir /a-d /b *test*.txt】,列出当期目录带有test的文本文件。
for命令在使用参数/d、/r时,也支持使用通配符。
参数/d,例如命令【for /d %%i in (f:\test*) do echo %%i】,会匹配f盘下的所有开头为test的文件夹。
参数/r,例如命令【for /r d:/root/test %%i in (.) do echo %%i】,会递归匹配d盘的root/test目录下的所有子文件夹。
但是参数/f不支持通配符,例如执行命令【for /f %i in (tool?.txt) do echo %i】,会报错找不到tool*.txt文件。
单冒号:和call、goto命令搭配使用。
单个的【:】开头,表示该行是一个位置标识行,之后的内容是一个程序段。
如【:test】,则表示【:test】之下的内容是程序段,而【test】是这个程序段的名,可以用【goto test】 、【goto :test】跳转到该程序段,或用【call :test】调用该程序段。
例如下面的代码!
- @echo off
- chcp 65001
- echo "主程序执行"
- call :end
- pause
-
- :end
- echo "子程序执行"
② 在 set 语句中:和~同时使用时,: 起到截取字符串的功能。假设 set str=abcde,那么,set var=%str:~0,1% 表示截取字符串abcde的第一个字符;和=同时使用时,起到替换字符串的功能。假设:set str=abc:de,那么,set var=%str:a=1% 则表示把字符串abc:de中的a替换为1,set var=%str::=2% 则表示把字符串abc:de中的:替换为2;
连续两个冒号开头,表示该行为注释。
下面从三个大点阐述双冒号【::】和rem注释语句的差别。
rem 注释语句中的某些命令符号如重定向符号和管道符号还是会执行,而如果用::来注释的时候,与::同处一行的所有命令或符号直接被命令解释器忽略掉,无形中提高了注释的兼容性和整个程序的执行效率,并且在众多的命令语句中更显得醒目。
只要没有执行echo off关闭命令行回显状态,rem开头的注释行就会回显。
与rem不同的是,::后的字符行在执行时不会回显,无论是否用echo on打开命令行回显状态,因为命令解释器不认为他是一个有效的命令行。
除了【::】之外,任何以【:】开头的字符行,在批处理中都被视作标号,而直接忽略其后的所有内容。
有效标号:冒号后紧跟一个以字母数字开头的字符串,【goto】语句可以识别。
无效标号:冒号后紧跟一个非字母数字的一个特殊符号,【goto】无法识别的标号,可以起到注释作用,所以【::】常被用作注释符号,其实【:+】也可起注释作用。
只是为了与正常的标号相区别,建议使用【goto】所无法识别的标号,即在【:】后紧跟一个非字母、也非数字的一个特殊符号,例如【:@】。
%0指批处理脚本文件本身,即便是双击执行脚本文件,也有意义。
%1-%9指用call命令在当前窗口调用或在直接用bat文件名重开窗口执行时,添加在后面的参数。
%10以及更大,则就不涉及形式变量了。而是一个形式变量加一个数字,例如%15,%1=1.bat时,%15就等于1.bat5。
一般不建议环境变量的名称设置为0-9,但是10以及往上还是可以的。
%*代表全部的批处理参数,也即代表%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文件中,双击执行试试,绝对会不断地“生孩子”哈哈哈。
利用命令【set /a X%Y】可以显示出X除以Y后的余数,注意这里是求余而不是取模(求余是和X符号相同,取模是与Y符号相同)。
在批处理脚本文件中,就必须连着写两个百分号来表示求余。因为这样是用前一个百分号对后一个百分号进行转义,将后面的%看做普通的求余字符,而不会看做批处理参数。
新建一个Bat文件,代码如下所示。
- @echo off
- set /a b=9%%2
- echo %b%
- set /a b=9%%-2
- echo %b%
- set /a b=-9%%2
- echo %b%
- pause
执行结果如下。
常和set、echo命令一起使用。
set命令可以设置变量、删除变量、查找(搜索)并显示变量。
echo命令可以打印/显示常量或变量。
那么问题来了,什么时候加双百分号,什么时候不加呢?这个问题涉及到CMD批处理的预处理机制,也即如果未开延迟变量,在一条语句中存在双百分号包裹的变量时,那么就会直接将其替换成这个变量所拥有的的值。
下面给一个经典的案例。
新建一个bat文件,代码如下。
- @echo off
- set b=1
- echo %b%
- set /a b=%b%+1
- echo %b%
- set /a b+=1
- echo %b%
- pause
双击执行结果如下。所以我们可以发现命令【set /a b+=1】和命令【set /a b=%b%+1】效果是一样的。
小结一下:对于echo命令,永远是将双百分号包裹住变量;而对于set命令,出现在等号右边则用双百分号包括,出现在等号左边就无需。
但是,当开启了“延迟变量”、“扩展变量”功能时,就需要将双百分号改成双感叹号,也即%xxx%改成!xxx!。
在【set】语句中,单冒号【:】和【~】同时使用时,起到截取字符串的功能。
如果第1个数是自然数,而第2个数是正整数;那么第1个数是起始序号,第2个数是从起始数开始向右取的字符数量。假设【set str=abcde】,那么,【set var=%str:~0,1%】表示截取字符串【abcde】的第一个字符。
如果第1个数不存在,而第2个数是负数-N,表示从右端向左数(右边第一个是-1)截取N个数。假设【set str=abcde】,那么,【set var=%str:~-2%】表示截取字符串【abcde】从右向左数两个字符,也即截取【de】。
如果第1个数是自然数M,而第2个数是负数-N,表示从第M+1个字符开始截取到倒数第N+1字符。假设【set str=abcde】,那么,【set var=%str:0~-2%】表示截取字符串【abcde】从第1个字符开始截取到倒数第3个字符,也即【abc】。
如果第1个数是负数-M,而第2个数是正整数N,表示从倒数第M个字符开始截取到第N+1个字符。假设【set str=abcde】,那么,【set var=%str:-4~2%】表示截取字符串【abcde】从倒数第4个字符开始截取到第3个字符,也即【bc】。
在【set】语句中,单冒号【:】和【=】同时使用时,起到替换字符串的功能。假设:【set str=abc:de】,那么,【set var=%str:a=1%】则表示把字符串【abc:de】中的a替换为1,【set var=%str::=2%】则表示把字符串abc:de中的【:】替换为【2】。
如果要显示%本身时,需要在前面用%来转义。
新建一个bat文件,代码如下
- @echo off
- chcp 65001
- echo 一个百分号:%%
- echo 两个百分号:%%%%
- echo 三个百分号:%%%%%%
- pause
双击执行,结果如下
另外,在for命令语句中,变量variable前面必须要加两个%号,也即批处理文件中除了批处理参数能单独用百分号,其他情况都需要用双百分号
- FOR /F ["options"] %%variable IN (file-set) DO command [command-parameters]
- FOR /F ["options"] %%variable IN ("string") DO command [command-parameters]
- FOR /F ["options"] %%variable IN ('command') DO command [command-parameters]
上面我们提到百分号%的输出需要依赖百分号它自己来实现。
那么有些特殊符号的输出依赖哪个符号呢?
一般而言,^以转义字符的身份出现。
因为在 cmd环境中,有些字符具备特殊功能,如>、>>表示重定向,|表示管道,&、&&、||表示语句连接……它们都有特定的功能,如果需要把它们作为字符输出的话,echo >、echo | ……之类的写法就会出错——cmd解释器会把它们作为具有特殊功能的字符对待,而不会作为普通字符处理。
这个时候,就需要对这些特殊字符做转义处理:在每个特殊字符前加上转义字符^。
因此,要输出这些特殊字符,就需要用 echo ^>、echo ^|、echo ^|^|、echo ^^……之类的格式来处理。
除了输出特殊字符会用到转义,在参数中不允许包括特殊字符时,也需要对其进行转义。
比如for /f命令语句的set字段是command时,不允许直接用特殊符号,如果有特殊符号就得经过上箭头(^)符号的转义,代码见下。
for /f "delims=\" %%i in ('fsutil fsinfo drives^|find /v ""') do echo %%i
equ、neq、lss、leq、gtr、geq命令符是if语句中常用到的数值比较符号。
取自英文的关键字母,具体的含义见下表。
命令符号 | 含义 | 英文解释 |
EQU | 等于 | equal |
NEQ | 不等于 | not equal |
LSS | 少于 | less than |
LEQ | 少于或等于 | less than or equal |
GTR | 大于 | greater than |
GEQ | 大于或等于 | greater than or equal |
在cmd命令中,一般以空格作为不同输入参数、不同开关之间的分隔符;但是有些命令语句支持以逗号【,】作为分隔符。
例如执行命令【dir,c:/】,结果如下。
为啥不同参数、主体分隔符和同一参数、主体分隔符不一样?
因为这样可以防止误将同一参数、主体识别成不同主体,防止将不同参数、主体识别成同一主体。
以dir命令为例,
一般来说同一参数、主体的分割符用分号,但是也不排除有些命令语句比较特殊,比如find命令的filepath参数,指定多个文件路径时就可以批量搜索;但是不同文件路径之间不能用分号【;】作为分隔符,只能用空格作为分隔符。
作者估计是因为filepath处于find命令所有参数的最后一个位置,即使用空格做分隔符也不会导致误识别成另一个参数、主体。
而dir命令,文件参数不在最后一个位置,自然不能用空格做分隔符了!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。