批处理基础
批处理基础
常用DOS命令
暂停提示 pause
pause
# 执行显示:请按任意键继续. . .显示信息 echo
输出提示信息
echo hello,world
echo i will come back关闭每条命令的回显
# 格式:@ 放在echo命令前面
@echo hello,world
@echo i will come back打开回显或关闭回显功能
# 格式:echo [{ on|off }]
# 1.如果在批处命令前加上echo off,那么将会关闭批处理中的命令回显
# 2.关闭该命令本身:把@加在echo off前面输出空行即输入一个回车
# 格式:echo.
# 1.注意命令中的“.”要紧跟在ECHO后面,中间不能有空格,否则“.”将被当作提示信息输出到屏幕
# 2.另外“.”可以用 , : ; " / ] + \ 这些任一符号替代
# 3.命令ECHO.输出的回车,经DOS管道转向可以作为其它命令的输入
echo. | time
# 上面命令相当于在TIME命令执行后给出一个回车
# 所以执行时系统会在显示当前时间后,自动返回到DOS提示符状态答复命令中的提问
# 格式:ECHO 回复 | 命令表达式
# 作用:通过管道命令 | 把“回复”作为输入传导给后面的“命令表达式”,并作为“命令表达式”的输入
# 例子:
rd /s d:\test
# 执行显示:c:\abc, 是否确认(Y/N)?
# 这里test是一个不为空的文件夹,用rd命令删除时它将会询问Y或N,这时就要手动的输入Y/N了
# 我们把批处理改一下,这时系统将会自动帮助我们把Y输入确认了
echo Y|rd /s d:\test建立新文件或增加文件内容
# 格式:echo 文件内容 > 文件名
# 建立一个文件内容为12的3myfile.txt文件
echo 123 > myfile.txt
# 建立一个myfile.txt空文件
echo. >myfile.txt注释 rem
# rem 为注释命令一般用来给程序加上注解,该命令后的内容不被执行但能回显
@echo off
echo hello world
rem 翻译为:你好世界
# 另外 :: 符号也可以起到 rem 的注释作用而且更简洁有效,但有两点需要注意!
# 1. 任何以冒号:开头的字符行,在批处理中都被视作标号,而直接忽略其后的所有内容
# 有效标号:冒号后紧跟一个以字母或数字开头的字符串,goto 语句可以识别标号
# 无效标号:冒号后紧跟一个非字母或数字的一个特殊符号,goto 无法识别标号,可以起到注释
# 所以 :: 常被用作注释符号,其实 : 也可起注释作用。
@echo off
echo hello world
:: 翻译为:你好世界
# 2. 与 rem 不同的是 :: 后的字符行在执行时不会回显,无论是否用echo on 打开命令行回显状态
# 因为命令解释器不认为他是一个有效的命令行,就此点来看 rem 在某些场合下将比 :: 更为适用
# 另外 rem 可以用于 config.sys 文件中目录切换 cd
# 1.同一个分区的切换
# 格式: cd [盘符][路径]
# 如果当前目录是D:\test,要切换到同一分区下不同的目录,如下:
# 注:下面例子中的 > 表示命令行下的提示符,> 前面的表示当前目录
D:\test>
cd D:\hello
D:\hello
# 2.切换到上级目录 ..\(可连续切换),切换到当前目录 .\
cd ..\..\
cd D:\
cd .\
# 3.返回当前盘符根目录
cd \
D:
# 4.显示当前的完整路径,通过 %cd% 加以引用
@echo off
echo 当前路径是 %cd%列文件名 dir
# 显示目录中的文件和子目录列表
dir [drive:][path][filename] [/A[[:]attributes]] [/B] [/C] [/D] [/L] [/N]
[/O[[:]sortorder]] [/P] [/Q] [/S] [/T[[:]timefield]] [/W] [/X] [/4]
[drive:][path][filename] # 指定要列出的驱动器、目录和/或文件。
# 参数释义
/A # 显示具有指定属性的文件
# attributes D 目录 R 只读文件
# H 隐藏文件 A 准备存档的文件
# S 系统文件 - 表示“否”的前缀
# 例子:dir /A:H 或 dir /AH
/B # 使用空格式(没有标题信息或摘要)。即简化方式打印
/C # 在文件大小中显示千位数分隔符。这是默认值。用 /-C 来停用分隔符显示
/D # 跟宽式相同,但文件是按栏分类列出的
/L # 用小写
/N # 新的长列表格式,其中文件名在最右边
/O # 用分类顺序列出文件。
# sortorder N 按名称(字母顺序) S 按大小(从小到大)
# E 按扩展名(字母顺序) D 按日期/时间(从先到后)
# G 组目录优先 - 颠倒顺序的前缀
# 例子:dir /O:S
/P # 在每个信息屏幕后暂停,即使用分页显示的方式列出一屏的目录及文件
/Q # 显示文件所有者
/S # 显示指定目录和所有子目录中的文件
/T # 控制显示或用来分类的时间字符域
# timefield C 创建时间
# A 上次访问时间
# W 上次写入的时间
/W # 用宽列表格式。
/X # 显示为非 8dot3 文件名产生的短名称。格式是 /N 的格式,
# 短名称插在长名称前面。如果没有短名称,在其位置则显示空白。
/4 # 用四位数字显示年
# 例子:关于dir命令比较多,在这里我们学习一些常用的就OK了
# 1.列出c:\windows下的目录及文件
# 这种方法有明显的缺点——当列表中的目录及文件过多时就无法完全显示
# 我们将通过/P参数解决这个问题
dir c:\windows
# 2.列出C:\下所有的文件夹,但不包含隐含的文件夹
dir /ad-h c:\
# 3.优先列出文件夹,并且文件夹和文件都按字母顺序排列
dir /ogn c:\
# 注意:/o 和 /a 都可以省略其后的冒号“:”
# 但之间不能留有空格。如“/o:n”省略后的形式应为“/on”。设置文件属性 attrib
# 显示或更改文件属性
ATTRIB [R|-R][A|-A][S|-S][H|-H][[drive:][path]filename][/S[/D]]
# 参数释义
- # 清除属性。
R # 只读文件属性。
A # 存档文件属性。
S # 系统文件属性。
H # 隐藏文件属性。
[drive:][path][filename] #指定要处理的文件属性。
/S # 处理当前文件夹及其子文件夹中的匹配文件。
/D # 也处理文件夹。
# 例子:
# 1.查看文件的文件属性
attrib d:\test.txt
# 2.修改文件的属性
# 消除 d:\test.txt 的"隐藏”属性
attrib –h d:\test.txt
# 给 d:\test.txt 设置“系统”和“隐藏”属性
attrib +s h d:\test.txt
# 3.批量文件处理
# 通过/s参数可批量将d:\test及其子目录下的所有bat文件设置为“隐藏”属性
attrib h d:\test\*.bat /s
# 将d:\test及其下所有同名为test的子目录设置为“隐藏”属性
# 参数/d必须在批量设置文件属性的同时,对指定目录及其下所有子目录进行文件属性操作
# 参数/d可以理解为“directory”(目录),也就是说/d 必需和/s一起使用
attrib h d:\test /s /d
# 思考:“attrib h d:\test /s /d”和“attrib h d:\test\*.* /s /d”有什么区别呢?
# => 前者只有d:\test以及它同名的子目录设为了“隐藏”,而其它文件及子目录都没有设置“隐藏”
# 后者则将d:\test下的所有文件及子目录设置了“隐藏”属性,但d:\tes目录没有设置“隐藏”属性删除 del
# 删除一个或数个文件
DEL [/P] [/F] [/S] [/Q] [/A[[:]attributes]] names
ERASE [/P] [/F] [/S] [/Q] [/A[[:]attributes]] names
# 参数释义
names # 指定一个或数个文件或目录列表。通配符可被用来删除多个文件
# 如果指定了一个目录,目录中的所有文件都会被删除
/P # 删除每一个文件之前提示确认
/F # 强制删除只读文件
/S # 从所有子目录删除指定文件
/Q # 安静模式。删除全局通配符时,不要求确认
/A # 根据属性选择要删除的文件
# attributes R 只读文件 S 系统文件
# H 隐藏文件 A 存档文件
# - 表示“否”的前缀
# 例子:
# 1.删除d:\test目录下所有文件
# 如果你想让它在删除前都询问你是否删除,我们可以加上/p参数防止误删除
del /p d:\test\*.*
# 2.删除d:\test目录及其子目录下所有文件
del /s d:\test\*.*
# 3.删除d:\test目录及其子目录下所有文件,
# 通过/q参数则无需确认直接删除,在使用此参数时要小心!!
del /s /q d:\test\*.*
# 4.删除d:\test目录及其子del /ar /s d:\123\*.*目录下所有只读属性的文件
del /ar /s d:\test\*.*复制文件 copy
注意:Copy只能复制文件,不能复制文件夹
单个文件的复制
copy source[drive:][path][filename] [destination [drive:][path][filename]]
# 即copy要复制的源文件(包括路径和文件名) 文件复制的目标路径[\文件名]
# 当[destination [drive:][path][filename]]缺省时则为当前目录
# 例1:把test.txt复制到d:\目录下。如果此操作成功,命令行窗口中会提示“已复制 1个文件”
copy c:\test.txt d:\
# 例2:把test.txt复制到d:\目录下,并把它修改为abc.bat,这里修改了文件名和它的格式
copy c:\test.txt d:\abc.bat
# 例3:把当前目录下的test子目录中的文件全部拷到当前目录。
copy .\test批量复制文件
# 例1:将c:\test 目录中所有文件复制到d:\abc目录中
copy c:\test\*.rm d:\abc /y
# 将c:\test目录中所有rm格式的文件复制到d:\abc目录中
# 通过参数/y(复制单个文件或批量复制时皆可使用),可以实现重名文件无须确认直接覆盖。合并文件
# 格式:copy /b 文件1+文件2+……文件N 合并后的文件名
# 例1:把1.mp3和2.mp3合并成3.mp3。
copy /b d:\1.mp3+d:\2.mp3 d:\3.mp3
# 例2:把1.txt和2.mp3合并,这里没有指定合成后的文件名
# 缺省情况下合并后的文件名是命令中的第一个文件的名
# 下面即把2.mp3合并进了1.txt:
copy /b d:\1.txt d:\2.mp3
# 注意:
# 1.在尾部隐藏了文本数据的图片文件,在使用其他软件进行编辑并保存后,隐藏的文本数据有可能会丢失
# 2.MP3文件在使用此方法连接后,能实现连续播放
# 3.合并图片/歌曲这样的二进制文件必须使用/b参数(b代表Binary,二进制),否则合并将会失败
# 另一个合并参是/a(a代表ASCII,文本文件),只能用于纯文本的合并。
# 两参数不能同时使用,二进制方式可以合并文本和二进制文件,而文本方式则只能合并文本。复制文件(夹) xcopy
# 复制文件和目录树
XCOPY source [destination] [/A | /M] [/D[:date]] [/P] [/S [/E]] [/V] [/W]
[/C] [/I] [/Q] [/F] [/L] [/G] [/H] [/R] [/T] [/U]
[/K] [/N] [/O] [/X] [/Y] [/-Y] [/Z]
[/EXCLUDE:file1[ file2][ file3]...]
Source # 必需的,指定要复制的文件的位置和名称,该参数必须包含驱动器或路径
Destination # 可省略,指定要复制的文件的目标
# 该参数可以包含驱动器盘符和冒号、目录名、文件名或者它们的组合
# 如果省略 Destination,xcopy 命令将文件复制到当前目录
# 参数释义(xcopy可使用的参数太多了,这里只选几个常用的释义)
/S # 复制非空的目录和子目录。如果省略 /s,xcopy 将在一个目录中工作
/E # 复制所有子目录,包括空目录。同时使用 /e、/s 和 /t 命令行选项
/H # 复制具有隐藏和系统文件属性的文件,默认情况下xcopy 不复制隐藏或系统文件
/T # 只复制子目录结构(即目录树)不复制文件。要复制空目录必须包含 /e 选项
/Y # 禁止提示您确认要覆盖现存的目标文件
# 例1:复制d:\test目录下所有文件(夹)到e:\kkk,不包括空的子目录。
# (默认情况下,xcopy 不复制隐藏或系统文件)
xcopy /s d:\test e:\kkk\
# 例2:复制d:\test目录下所有文件(夹)到e:\kkk,包括空的子目录
# (默认情况下,xcopy 不复制隐藏或系统文件)
xcopy /e d:\test e:\kkk\
# 例3:复制d:\test目录下所有文件(夹)到e:\kkk,包括空的子目录。
# 加上了/h参数后,xcopy 复制隐藏或系统的文件
xcopy /e /h d:\test e:\kkk\
# 注意:
# 1.注意指定 Destination 是文件还是目录。
# 如果 Destination 不包含现有目录且不以反斜杠 (\) 结尾,会出现下列消息:
Does destination specify a file name
or directory name on the target
(F = file, D = directory)?
# 统将会询问你目标 X:\XXX 是文件名还是目录名 (F = 文件,D = 目录)?
# 如果要将一个或多个文件复制到一个文件请按 F。如果要将一个或多个文件复制到一个目录请按 D
# 思考:
# 比较一下xcopy /e d:\test e:\kkk\ 和 xcopy /e d:\test e:\kkk 两者之间有什么不同?
# => 两者都是复制d:\123目录下所有文件(夹)到e:\kkk,包括空的子目录
# 但前者不会询问你目标e:\kkk 是文件名还是目录名(F = 文件,D = 目录)?创建文件夹 md
md命令用于创建文件夹,下面例子中的路径是可以缺省的,如果缺省则在当前目录下创建新文件夹;如果创建的新文件夹及其路径带有空格或特殊符号的,要用双引号括起来。
# 创建单个文件夹
# 格式:MD [路径\]目录
md d:\test # 在D盘下建立一个名为abc的文件夹
md test # 这里为缺省路径,则在当前目录下创建一个名为test的文件夹
md "d:\my test" # 有空格或是特殊符号的,一定要用双引号把文件夹名括起来
# 同时创建多个目录
# 格式:md [路径\]目录1 [路径\]目录2 [路径\]目录3...
md test1 D:\gmae\test test2
# 创建多级目录
# 格式:md [路径\]目录1\目录2\目录3\...
md d:\abc\abcd\abcde删除文件夹 rd
# 删除一个目录
# 格式1:RMDIR [/S] [/Q] [drive:]path
# 格式2:RD [/S] [/Q] [drive:]path
/S # 除目录本身外,还将删除指定目录下的所有子目录和文件。用于删除目录树。
/Q # 安静模式,带 /S 删除目录树时不要求确认重命名文件(夹) rd
# 重命名文件
# 格式1:RENAME [drive:][path]filename1 filename2.
# 格式2:REN [drive:][path]filename1 filename2.
# 单个文件的重命名
ren d:\123.txt 456.bat
# 批量重命名(通过 * 和 ? 这两个通配符来批量重命名。* 表示任意多个字符,? 表示一个字符)
ren *.bat *.txt # 把后缀名为bat的文件批量更改为txt后缀后的文件
# 注意:
# 当文件具有隐藏属性或系统属性的时候ren不能直接重命名,需要把文件的隐藏或系统属性去掉方可更名!删除文件(夹) move
# 移动文件并重命名文件和目录
# 要移动至少一个文件格式:MOVE [/Y | /-Y] [drive:][path]filename1[...] destination
# 要重命名一个目录:MOVE [/Y | /-Y] [drive:][path]dirname1 dirname2
[drive:][path]filename1 # 指定您想移动的文件位置和名称。
destination # 指定文件的新位置。目标可包含一个驱动器号和冒号、一个目录名或组合。
# 如果只移动一个文件并在移动时将其重命名,您还可以包括文件名。
[drive:][path]dirname1 # 指定要重命名的目录。
dirname2 # 指定目录的新名称。
/Y # 取消确认改写一个现有目标文件的提示
/-Y # 对确认改写一个现有目标文件发出提示
# 移动文件(夹)
move d:\abc d:\abcd # 把文件夹abc移到文件夹abcd内
move 123.txt abc # 当前目录下的123.txt移动到当前文件夹abc内
# 重命名文件(夹)
# 如果目标文件夹abcd不存在,则把abc移到d:\下,并把自身名称更改为abcd。利用这一特性,move命令具备重命名功能
move d:\abc d:\abcd
move d:\123.txt d:\abc\456.txt
# 注意:
# 1. MOVE命令可以跨分区移动文件,却不可以跨分区移动文件夹。
# 2. 对于跨分区移动文件时如果目标位置存在和将要移动的文件同名时,
# 系统会提示:“文件存在” 最后,命令将不会执行
# 3. 对于隐藏或系统属性的文件,只有把它们的属性去除后,move命令才会执行字符串查找 find
# 在文件中搜索字符串
# 格式:FIND [/V] [/C] [/N] [/I] [/OFF[LINE]] "string" [[drive:][path]filename[ ...]]
/V # 显示所有未包含指定字符串的行
/C # 仅显示包含字符串的行数
/N # 显示行号
/I # 搜索字符串时忽略大小写
/OFF[LINE] # 不要跳过具有脱机属性集的文件
"string" # 指定要搜索的文字串
[drive:][path]filename # 指定要搜索的文件字符串查找增强 findstr
了,可能是在查找多个纯中文字符串的时候的一个bug吧;单个的纯中文字符串没有任何问题。# 在文件中寻找字符串
# 格式:FINDSTR [/B] [/E] [/L] [/R] [/S] [/I] [/X] [/V] [/N] [/M] [/O] [/F:file]
# [/C:string] [/G:file] [/D:dir list] [/A:color attributes] [/OFF[LINE]]
# strings [[drive:][path]filename[ ...]]
/B # 在一行的开始配对模式
/E # 在一行的结尾配对模式
/L # 按字使用搜索字符串
/R # 将搜索字符串作为一般表达式使用
/S # 在当前目录和所有子目录中搜索匹配文件
/I # 指定搜索不分大小写
/X # 打印完全匹配的行
/V # 只打印不包含匹配的行
/N # 在匹配的每行前打印行数
/M # 如果文件含有匹配项,只打印其文件名
/O # 在每个匹配行前打印字符偏移量
/P # 忽略有不可打印字符的文件
/OFF[LINE] # 不跳过带有脱机属性集的文件
/A:attr # 指定有十六进位数字的颜色属性。请见 "color /?"
/F:file # 从指定文件读文件列表 (/ 代表控制台)
/C:string # 使用指定字符串作为文字搜索字符串
/G:file # 从指定的文件获得搜索字符串。 (/ 代表控制台)
/D:dir # 查找以分号为分隔符的目录列表
strings # 要查找的文字
[drive:][path]filename # 指定要查找的文件
# 1. 除非参数有 /C 前缀,请使用空格隔开搜索字符串
'FINDSTR "hello there" x.y' # 在文件 x.y 中寻找 "hello" 或"there"
'FINDSTR /C:"hello there" x.y' # 在文件 x.y 寻找 "hello there"
# 2. /R 将搜索字符串作为正则表达式使用。参数/R 强调以正则表达式规则来解读字符串
# R - Right 右即为正。右手是正手,因此引申为右为正,左为反
findstr /r "icq msn" 123.txt # 在123.txt中查找包含有 “icq”或“msn”的行
# 3. 在使用 findstr "我 你 他" test.txt 的时候,并不能查找到内容,但是加上开关 /i 或者 /r 之后就正
# 确无误了,可能是在查找多个纯中文字符串的时候的一个bug吧;单个的纯中文字符串没有任何问题。
# 4. findstr 命令中正则表达式的用法规则
# 一般表达式的快速参考:
. # 通配符: 任何字符
* # 重复: 以前字符或类别出现零或零以上次数
^ # 行位置: 行的开始
$ # 行位置: 行的终点
[class] # 字符类别: 任何在字符集中的字符
[^class] # 补字符类别: 任何不在字符集中的字符
[x-y] # 范围: 在指定范围内的任何字符
\x # Escape: 元字符 x 的文字用法
\<xyz # 字位置: 字的开始
xyz\> # 字位置: 字的结束
# 例1:在文件123.txt中查找任意字符,不包括空行
findstr . 123.txt
findstr "." 123.txt
# 例2:在文件123.txt中查找任意字符,包括空行
findstr .* 2.txt
findstr ".*" 2.txt
# 例3:在文件123.txt中查找出现一个“a”字符串,以及a后面出现过0次或者任意次c的字符行
# 如a、ac、acc、addc
findstr ac* 123.txt
# 例4:在文件123.txt中查找出现一个“ak”字符串,以及ak后面出现过0次或者任意次5的字符行
# 如ak、ak5、akbbb、ak125、ak555
findstr ak5* 123.txt
# 例5:在文件123.txt中查找数字0-9的任意之一的行
# 如4kkb、1 lkka cc
findstr "[0-9]" 123.txt
# 例6:在文件123.txt中查找包括a b c e z y其中任意一字母的行
findstr "[abcezy]" 123.txt
# 例7:在文件123.txt中查找小写字符a到f 或l到z的任意一字母的行,但不包含g h I j k这几个字母
indstr "[a-fl-z]" 123.txt
# 例8:如果是纯数字的行便过滤掉,例如2323423423 这样的字符串被过滤,345hh888这样的形式则过滤不了
# 注意纯数字的行不能有空格,不论行首行尾或者是行中都不能有空格,否则过滤失败!(字母也是如此)
findstr "[^0-9]" 123.txt
# 例9:过滤仅含有由e c h o 四个字母组成的纯字母字符串的行
# 如如:e、c、ec、cho、chooo
findstr "[^echo]" 123.txt
# 例10:所有含有以echo为前缀的字符串的行,都匹配
# 如 echo:kkk a add、jjkk echo、:echo
findstr "\<echo" 123.txt
# 例11:所有含有以echo为后缀的字符串的行,都匹配
# 如qq bbecho、kkkk echo:
findstr "echo\>" 123.txt
# 例12:精确查找单词。查找单词end的行(ended、cdkend、bcd-end-jjkk这类词都不匹配)
# 如end echo、end
findstr "\<end\>123.txt
# 例13:在文件123.txt中查找可以匹配“.abc”字符串的行,这里\.是把.给转义了
findstr "\.abc" 123.txt
# 例14:在文件123.txt中查找可以匹配“1\”字符串的行,这里\\是把\给转义了
findstr "1\\" 123.txt
findstr "1\\\\" 123.txt
# 注意:
# 要查找的字符串含有\时,可以用\\把\给转义;或者把\变成\\\\。
# 如果目标字符串的\后面还有内容,则搜索字符串\除了要变成\\(本身的转义要求),
# 还可以在它后面再加一个字符,如\\.常用网络命令
测试IP连接 ping
# 用来检查网络是否通畅或者网络连接速度的命令
# 1. 发送count指定的Echo数据包数
# 定义向目标IP发送数据包的次数,默认为4次
# 通过此命令可以收集到一些信息。
# 如数据包返回的平均时间为多少,最快时间为多少,最慢时间为多少等等
-n count
# 例1:
ping -n 3 www.baidu.com
# 正在 Ping www.a.shifen.com [14.215.177.39] 具有 32 字节的数据:
# 来自 14.215.177.39 的回复: 字节=32 时间=38ms TTL=55
# 来自 14.215.177.39 的回复: 字节=32 时间=37ms TTL=55
# 来自 14.215.177.39 的回复: 字节=32 时间=37ms TTL=55
#
# 14.215.177.39 的 Ping 统计信息:
# 数据包: 已发送 = 3,已接收 = 3,丢失 = 0 (0% 丢失),
# 往返行程的估计时间(以毫秒为单位):
# 最短 = 37ms,最长 = 38ms,平均 = 37ms
# 例2:
ping -n 11 127.0.0.1 >nul
# ping本机11次,可用于批处理延时10秒。命令中的>nul为屏蔽输出
# 简短式可以写成:
ping -n 11 127.1 >nul
# 2. 等待每次回复的超时时间(毫秒)
# 如果我将超时时间设置很短,例如10毫秒,那么如果发出一个数据包10毫秒
# 内没有收到应答包的话,就给出请求超时的提示
-w timeout查看IP配置 ipconfig
# 由于批处理中经常对计算机的TCP/IP 配置信息的截取
# 这里只列出/all参数就行了
/all
# 显示所有适配器的完整 TCP/IP 配置信息。
# 当使用ipconfig时不带任何参数选项,那么它为每个已经配置了的接口显示IP地址、子网掩码和缺省网关值解析地址 arp
# 显示和修改“地址解析协议 (ARP)”缓存中的项目
# ARP 缓存中包含一个或多个表,它们用于存储 IP 地址及其经过解析的以太网或令牌环物理地址。
# 计算机上安装的每一个以太网或令牌环网络适配器都有自己单独的表
# 1. 用于查看高速缓存中的所有项目。-a和-g参数的结果是一样的,多年来-g一
# 直是UNIX平台上用来显示ARP高速缓存中所有项目的选项而Windows用的是
# arp -a(-a可被视为all即全部的意思),但它也可以接受比较传统的-g选项
-a
-g
# 如果我们有多个网卡,那么使用arp –a 加上对应网卡的IP地址,就可以只显示
# 与该网卡相关的ARP缓存项目。
arp -a IP
# 缺省IP情况下,将显示所有当前 ARP 缓存表
arp -a
# 接口: 192.168.56.1 --- 0xc
# Internet 地址 物理地址 类型
# 192.168.56.255 ff-ff-ff-ff-ff-ff 静态
# 224.0.0.2 01-00-5e-00-00-02 静态
# 224.0.0.22 01-00-5e-00-00-16 静态
# 224.0.0.251 01-00-5e-00-00-fb 静态
# 224.0.0.252 01-00-5e-00-00-fc 静态
# 239.255.255.250 01-00-5e-7f-ff-fa 静态
# ...
# 2. 我们可以向ARP高速缓存中人工输入一个静态项目。该项目在计算机引导过程中
# 将保持有效状态,或者在出现错误时,人工配置的物理地址将自动更新该项目。
# 通过此命令可以实现ARP绑定
# 对192.168.1.1添加静态ARP实现ARP绑定
arp -s 192.168.1.1 00-1a-92-90-19-fe
# 3. 使用arp -d命令能够人工删除一个静态项目。
# 缺省IP情况下将删除当前计算机的arp表。
# 在对付ARP欺骗中,我们一般先删除当前计算机的arp表,然后再实现ARP绑定
arp -d IP开启命令 start
# 基本格式:start "title" filename
# 其中title可以省略,filename如带有空格或是特殊符号的,用""括起来
# 例1:打开百度,title省略了
start http://www.baidu.com
# 例2:用NOTEPAD(记事本)打开 abc.txt
start %windir%\system32\NOTEPAD.EXE" "abc.txt"
# 例3:这里start后面要加""才能启动文件abc.doc,否则不能启动
# 如果start 后没有 "" 则表示把title省略了,此时文件名若有""的话
# start就会把它看作是标题,从而变成了省略文件名,就默认开启cmd了。
# 所以在start后加上""就能防止这种意外的情况
start "" "abc.doc"
# 使开启的窗口最小化和最大化
/min
/max
# 例4:用记事本最小化打开abc.txt
start /min notepad "abc.txt"关闭或重启计算机 shutdown
# 格式:shutdown [-i | -l | -s | -r | -a] [-f] [-m \\computername] [-t xx] [-c "comment"] [-d up:xx:yy]
-i # 显示 GUI 界面,必须是第一个选项
-l # 注销(不能与选项 -m 一起使用)
-s # 关闭此计算机
-r # 关闭并重启动此计算机
-a # 放弃系统关机
-m \\computername # 远程计算机关机/重启动/放弃
-t xx # 设置关闭的超时为 xx 秒
-c "comment" # 关闭注释(最大 127 个字符)
-f # 强制运行的应用程序关闭而没有警告
-d [u][p]:xx:yy # 关闭原因代码
u # 是用户代码
p # 是一个计划的关闭代码
xx # 是一个主要原因代码(小于 256 的正整数)
yy # 是一个次要原因代码(小于 65536 的正整数)
# 例1:该命令只能注销本机用户,对远程计算机不适用
shutdown -l
# 例2:通过-s参数,在12:00执行关闭计算机
at 12:00 shutdown -s
# 例3:60秒后重启计算机。
# 这里是设置重启倒计时为60秒。如果没有设置时间则默认为30秒
shutdown -r -t 60
# 例4:通过-f参数强制计算机300秒后关闭
shutdown -f -s -t 300
# 例5:当遇到冲击波或震荡波病毒时,或是执行了上面的关机命令时,可以运用
# shutdown -a 终止当前的关机进程,这样就可以避免关机而造成的损失了
shutdown -a关闭指定进程 taskkill
# Taskkill命令可以根据进程 ID 或图像名来结束一个或多个任务或进程
# 1.指定将终止的进程的图像名称,
/im ImageName
# 例如:taskkill /im qq.exe
# 2.指定将强制终止的进程。对于远程进程可忽略此参数所有远程进程都将被强制终止
/f process
# 例如:taskkill /f /im spoolsv.exe
# 3.指定要终止的进程的PID
/pid process id
# 例如:taskkill /pid 1230 /pid 1241 /pid 1253regsvr32
netsh
sc
wmic
常用特殊符号
重定向符 >、>>
# >为覆盖、>>为追加(以下所有的 > 都可以替换为 >> )
# 1. 重定向符, 意思是传递并且覆盖
# 它所起的作用是将运行的结果传递到后面的范围
# 后边可以是文件,也可以是默认的系统控制台,即命令提示符
# 例1:新建立文件 1.txt内容为”hello120”
# 注意:行尾有一空格,文件后有一空行
echo hello120 >1.txt
# 例2:新建立文件 1.txt,内容为”hello120”
# 注意:行尾无空格,但文件后有一空行
(echo hello120)>1.txt
# 或
>1.txt echo hello120
# 例3:新建立文件 1.txt,内容为”hello120”
# 注意:行尾无空格,且文件后也无空行
>1.txt <nul set /p=hello120
# 或
>1.txt set /p=hello120<nul命令管道符 |
# 表示把在它之前的命令或语句的执行结果作为在它之后的命令或语句的处理对象
# 简而言之,就是把它之前的输出作为它之后的输入
# 例1:将tasklist(进程列表)用传递符 "|" 传递给find 命令
# 执行查找QQ的进程
tasklist | find /i "qq.exe" && taskkill /f /im qq.exe
# 例2:通过管道命令|将 echo y 的结果传给rd /s c:\abc 命令
# 从而达到自动输入y 的目的
echo Y | rd /s c:\abc组合命令 &、&&、||
# &、&&、|| 为组合命令,顾名思义,就是可以把多个命令组合起来当一个命令来执行
# 1.&符号允许同时执行多条命令,当第一个命令执行失败了也不影响后边的命令行。
# 这里 & 两边的命令是顺序执行的,从前往后执行。
# 格式:第一条命令 & 第二条命令 [& 第三条命令...]
# 例1:以下命令会连续显示z,y,c 盘的内容,不理会该盘是否存在
dir z:\ & dir y:\ & dir c:\
# 2.&&符号允许同时执行多条命令,当碰到执行出错的命令后将不再执行后面的命令
# 如果一直没有出错则一直执行完所有命令
# 格式:第一条命令 && 第二条命令 [&& 第三条命令...]
# 例2:这个命令和上面的类似
# 区别是前一个命令执行失败时后边的命令就不会再执行了
dir z:\ && dir y:\ && dir c:\
# 3. ||符号允许同时执行多条命令,当一条命令执行失败后才执行第二条命令当碰到
# 执行正确的命令后将不执行后面的命令,如果没有出现正确的命令则一直执行完所
# 有命令
# 格式:第一条命令 || 第二条命令 [|| 第三条命令...]
# 例3:通过&&和||两个符号可以认为把下例分成了三个命令:
tasklist|find /i "qq.exe" && taskkill /f /im qq.exe || echo h注意:
组合命令和重定向命令、管道命令一起使用必须注意优先级。
管道命令的优先级高于重定向命令,重定向命令的优先级高于组合命令
转义字符 ^
# 1. 一般而言,^ 以转义字符的身份出现。因为在cmd环境中,有些字符具备特殊功
# 能,如 >、>>表示重定向,| 表示管道,&、&&、|| 表示语句连接它们都有
# 特定的功能,如果需要把它们作为字符输出的话,echo >、echo |之类的写
# 法就会出错。
# 2. cmd解释器会把它们作为具有特殊功能的字符对待而不会作为普通字符处理,这
# 个时候,就需要对这些特殊字符做转义处理:在每个特殊字符前加上转义字符
# ^。
# 3. 因此,要输出这些特殊字符,就需要用 echo ^>、echo ^|、echo ^|^|、
# echo ^^之类的格式来处理
# 4. 另外,此转义字符还可以用作续行符号
# 例1:转义字符用作续行符号,为什么转义字符放在行尾可以起到续行符的作用呢?
# 原因很简单,因为每行末尾还有一个看不见的符号,即回车符,转义字符位于行
# 尾时就让回车符失效了,从而起到了续行的作用
@echo off
echo 这是^
一个^
句子
Pause变量引导符 %
# 1. 当百分号成对出现并且其间包含非特殊字符时,一般做变量引用处理
# 比如:%var%、%str%
# 2.另外,百分号作为变量引用还有一种特殊形式,那就是对形式参数的引用
# 此时,单个百分号后面紧跟0~9这10个数字,如%0、%1、%2 ...
%0 # 表示批处理文件本身,包括完整的路径和扩展名
%1 ~%9 # 表示第一个参数至第九个参数
# 例子:假设批处理文件名:test.bat,内容为:
@echo off
echo %0
echo %1
echo %2
echo %3
# 执行该命令 `test.bat hello world boy` 输出结果为:
test.bat
hello
world
boy
# 3. 出现在 set /a 语句中时表示两数相除取余数,也就是所谓的模运算
# 它在命令行窗口和批处理文件中的写法略有差异:
# 在命令行窗口中只需要单个的%
# 在批处理文件中,需要连续两个百分号,写成%%
# 例子:
@echo off
set /a num=4%%2
echo 4除以2的余数为 %num%
pause
# 4.转义符号:如果要显示%本身时,需要在前面用%来转义
# 例子:
@echo off
echo 一个百分号:%%
echo 两个百分号:%%%%
echo 三个百分号:%%%%%%
pause界定符 ""
# 1. 在表示带有空格或特殊符号的路径时常要用""来将路径括起来
# 例子:因为路径中带有空格和特殊符号,所以要用""将路径括起来
cd /d cd "d:\program files\^%*abc"
# 2. 表示其中的内容是一个完整的字符串
# 例子:这里表示变量var的值为字符串“abc 123”
@echo off
set "var=abc 123"
echo %var% 77676if 语句
# 1.判断两个字符串是否相等
# 语法:if"字符串1"=="字符串2" command 语句
# 注意:在"字符串1"=="字符串2"中,是两个连续的"="
# 例1: 比较两个字符串是否相等
# 注意:在判断字符串是否相等的时候,if会区分大小写
# 如果我们不想让它区分大小写,则可以加上/i 参数
@echo off
set var1=a
set var2=A
if "%var1%"=="%var2%" (echo "Yes") else echo "No"
if /i "%var1%"=="%var2%" (echo "Yes") else echo "No"
pause
# 2. 判断两个数值是否相等
# 语法:if 数值1 equ 数值2 command 语句
# 参数:
# 中文含义 关系符 英文解释
# 等于 equ equal
# 大于 gtr greater than
# 大于或等于 geq greater than or equal
# 小于 lss less than
# 小于或等于 leq less than or equal
# 不等于 neq no equal
# 例1: 比较两个数字是否相等
# 注意:if 比较字符串与比较数字之间的区别
# 它们的区别体现在引号""上面
@echo off
set var1=2
if %var% geq 10 (echo "yes") else echo "no"
pause
# 例2: 比较两个数字字符串是否相等
@echo off
if "12" lss "4" (echo 字符串12小于4) else echo 字符串12大于4
pause
# 执行的结果是:字符串12小于4
# 为什么中加了数字加了双引号""会出错?原因如下:
# 如果要比较的两个元素加了双引号""那么会被当成是字符的比较。
# 两个元素作比较的流程是:先比较两个元素的首位,如果首位相同,再比较第二位
# 如果第二位相同,再比较第三位。。。依此,在 if "12" lss "4" 语句中
# 实质是1与4的比较,1 当然小于4,所以执行了后面的命令:echo 字符串12小于4
# 3. 判断判断驱动器,文件或文件夹是否存在
# 语法:if exist filename command 语句
# 例1:判断驱动器是否存在
@echo off
if exist "e:" (echo e盘存在) else echo e盘不存在
pause>nul
# 例2:判断按文件不存在(不严谨的语法)
# 这个例子是用来判断123.bat文件是否存在的,但并不严谨!
# 如果123.bat是一个文件夹而不是一个文件时,下面面的判断就不行了!
# 那么如何判断指定的文件123.txt是否存在?
@echo off
if exist d:\123.bat (echo 123.bat文件存在!) else echo 123.bat文件不存在!
pause
# 例3:判断按文件不存在(正确的语法)
# 先用dir的/a-d参数去除123.bat的目录属性,指定说明要搜索的123.bat是文件而不是文件夹
# 并把结果(包括正确和错误)屏蔽(>nul 2>nul),如果dir找到了文件123.bat,
# 那么其errorlevel值(dir命令的退出编码)会被设为0,否则为1则是没有此文件。
# 当然也可以用||和&&来判断。
# 关于为什么要用if %errorlevel%==0 而不用if errorlevel 0呢?
# 在后面if errorlevel中会有说明!
@echo off
dir /a-d d:\123.bat >nul 2>nul
if %errorlevel%==0 (echo 123.bat文件存在!) else echo 123.bat文件不存在!
Pause
# 例4:判断文件夹是否存在
@echo off
if exist test\ (echo test 是文件夹) else echo test 是文件
pause
# 例5:判断变量是否已经定义 [if defined 变量 command 语句]
# 执行后显示:变量 a 没有被定义
@echo off
if defined a (echo 变量 a 已定义) else (echo 变量 a 没有被定义)
pause
# 执行后显示:变量 a 没有被定义。注意:set a=这后面是没有空格的
@echo off
set a=
if defined a (echo 变量 a 已定义) else (echo 变量 a 没有被定义)
pause
# 执行后显示:变量 a 已定义
@echo off
set a=10
if defined a (echo 变量 a 已定义) else (echo 变量 a 没有被定义)
pause
# 当我们用 [if defined 变量 command] 语句判断变量是否被定义时
# 请注意 变量 为不使用引导符号%的变量名,不能用写为%变量%否则出错。
@echo off
set var1=5
if defined var1 (echo 变量var1已定义) else (echo 变量var1没有被定义)
set /p var2=请输入一个数字:
if defined %var2% (echo 变量var2已定义) else (echo 变量var2没有被定义)
set /p var3=请输入一个数字:
if defined var3 (echo 变量var3已定义) else (echo 变量var3没有被定义)
pause
# 4. 判断上个命令的反回值
# 语法:if errorlevel 数值 command 语句
# 例一:
# 注意:%errorlevel% 这是个系统变量,所以用两个%括起来
@echo off
net user
if %errorlevel% == 0 (echo net user 命令执行成功) else (echo net user 命令执行失败)
Pause
# 例2:if errorlevel 语句的特点
# 当使用 if errorlevel 0 cmmand 句式时它的含义是:
# 如果返回的错误码值大于或等于0 的时候,将执行cmmand操作
# 当使用 if %errorlevel%==0 cmmand 句式时它的含义是:
# 如果返回的错误码值等于0 的时候,将执行cmmand操作。
# 5. if 的两种格式
# 完整格式:if 条件表达式 (语句1) else (语句2)
# 简单格式:if 条件表达式 (语句)
# 6. if not 语句
# 对于if 语句前面的几种基本语法,都可以加上not参数
# 7. if的嵌套写法
# 例一:这是一种比较规范的写法
@echo off
set a=55
if %a% geq 50 (
if %a% geq 80 (
if %a% geq 100 (
echo a大于等于100
) else echo a小于100
) else echo a小于80
) else echo a小于50
pauseset语句
设置自定义变量
# 格式:set [variable=[string]]
# variable 指定环境变量名。 string 指定要指派给变量variable的一系列字符串
# 例1
# set var=abcd 是批处理设置变量的方法。
# Var是变量名,而abcd则是变量名var的值。
# echo %var% ,在批处理中我们要引用这个变量就把 var 变量名用两个%(百分号)扩起来,如%var%
@echo off
set var=abcd
echo %var%
pause
# 例2
# 以下用法将清除变量 var 的值,使其变成未定义状态
# 等号后面无任何符号,如果写成SET var1="",此时变量值并不为空,而是等于两个引号,即""
@echo off
set var=
set var1=""
if defined var (echo var的值为%var%) else echo var没有赋值
if defined var1 (echo var1的值为%var1%) else echo var1没有赋值
pause
# 例3
# set还可以提供一个交互界面让用户自己输入变量的值,然后我们在来根据这个值来做相应操作
# 现在我就来说说set的这种语法,只需要加一个"/P"参数就可以了!
# 执行下面的批处理时,系统会提示你:“请输入变量的值:”
@echo off
set /p var=请输入变量的值:
echo 您输入了%var%
pause字符串处理
# 1. 字符串替换
# 格式:%PATH:str1=str2%
# 意思就是:将字符串变量%PATH%中的str1 替换为str2
@echo off
set a= bbs. bathome. cn
echo 替换前的值: "%a%"
set var=%a: =%
echo 替换后的值: "%var%"
pause
# 执行后显示:
# 替换前的值: " bbs. bathome. cn"
# 替换后的值: "bbs.bathome.cn"
# 2. 字符串截取
# 格式:%a:~[m[,n]]%
# 方括号表示可选,%为变量标识符,a为变量名不可少,冒号用于分隔变量名和说明部分
# 符号~可以简单理解为“偏移”即可,m 为偏移量(缺省为0),n 为截取长度(缺省为全部)
@echo off
set a=bbs.bathome.cn
set var=%a:~1,3%
echo %var%
pause
# 执行显示为:bs.
# 我们来分析一下set var=%a:~1,3% ,这里%a:~1,3%就是说变量 a 偏移量为1,要截取它的3位字符长度。
# 合起来就是把变量 a 的值从第 2 位(偏移量 1)开始,截取 3 个字符赋予变量var
# 用法:
a=bbs.bathome.cn
%a:~1,3% -------- “bs.” # 变量a 偏离1位,截取3位字符。
%a:~1,-3% -------- “bs.bathome” # 变量a 偏离1位,截取倒数第3位前的字符。
%a:~-3% -------- “.cn” # 变量a 偏离-3位,截取倒数的3位字符。
%a:~-3,2% -------- “.c” # 变量a 偏离-3位,截取倒数后3位的前两2位字符
%a:~3% -------- “.bathome.cn” # 变量a 偏离3位,截取完后面的字符。
%a:~,3% -------- “bbs” # 变量a 偏离0位,截取3位字符。简单计算
# 格式:set /a expression
# /a 命令行开关指定等号右边的字符串为被评估的数字表达式。
# 该表达式评估器很简单并以递减的优先权顺序支持下列操作:
( ) # 分组
! ~ - # 一元运算符
* / % # 算数运算符
- # 算数运算符
<< >> # 二进制逻辑移位
& # 二进制按位“与”
^ # 二进制按位“异”
| # 二进制按位“或”
= *= /= %= = -= # 算数赋值
&= ^= |= <<= >>= # 二进制运算赋值
, # 表达式分隔符
# set 的/a 参数就是让set可以支持数学符号进行加减等一些数学运算, 注意:一般的运算常为十进制运算
# 例1:
# 注意:DOS 计算只能进行整数运算,精确到整数,它是不支持浮点计算的!
@echo off
set /p input=请输入计算表达式:
set /a var=%input%
echo 计算结果:%input%=%var%
pausefor循环语句
在批处理中for是最为强大的命令语句,它的出现使得解析文本内容、遍历文件路径、数值递增/递减等操作
成为可能。
配合if、call、goto等流程控制语句,更是可以实现脚本复杂的自动化、智能化操作。合理使用for语句,
还能使代码大为简化,免除各位编写大量重复语句之苦。
基本用法
# for语句的基本要素:
# 1、for、in和do是for语句的关键字,它们三个缺一不可
# 2、%%I是for语句中对形式变量的引用,就算它在do后的语句中没有参与语句的执行,也是必须出现的
# 3、in之后,do之前的括号不能省略
# 4、command1和command2表示字符串、变量或命令语句
# 例1:最基础的for语句
@echo off
for %%I in (bbs.bathome.cn) do echo %%I
pause
# for语句的使用注意项
# 其中第3点是最为关键的,它描述了for语句的执行过程,是for语句的精髓所在!!
# 1、for语句的形式变量I可以换成26个字母中的任意一个,这些字母会区分大小写,也就是说%%I和%%i会被认为不是同一个变量;形式变量I还可以换成其他的字符,但是为了不与批处理中的%0~%9这10个形式变量发生冲突,请不要随意把%%I替换为%%0 ~%%9中的任意一个
# 2、in和do之间的command1表示的字符串或变量可以是一个也可以是多个,每一个字符串或变量我们称之为一个元素,每个元素之间,用空格键、跳格键、逗号、分号或等号分隔
# 3、for语句依次提取command1中的每一个元素,把它的值赋予形式变量I带到do后的command2中参与命令的执行;并且每次只提取一个元素,然后执行一次do后的命令语句,而无论这个元素是否被带到command2中参与了command2的运行;当执行完一次do后的语句之后再提取command1中的下一个元素,再执行一次command2,如此循环直到command1中的所有元素都已经被提取完毕,该for语句才宣告执行结束;
# 例2:
# 和例1的执行结果相比,例2的执行结果发生了如下变化:
# 1、显示结果分成了3行(不算最后一行中文提示);
# 2、每一行都从逗号处被切分
@echo off
for %%I in (bbs,bathome,cn) do echo %%I
pause
# 如果把 bbs.bathome.cn 这个字符串中的点号换为空格、跳格或等号,执行结果将和例2的执行结果别无二致
# 例3:检测当前磁盘有哪些分区
# 这段代码能检测硬盘都有哪些分区,包括U盘和移动硬盘的分区,但是当光驱中有盘的时候也会被列出来
# 这是本代码的一个缺憾
@echo off
set str=c d e f g h i j k l m n o p q r s t u v w x y z
echo 当前硬盘的分区有:
for %%i in (%str%) do if exist %%i: echo %%i:
pause
# 例4:当前目录下文件打印
@echo off
for %%i in (*.*) do echo "%%i"
pause
# 例5:只用两个字符作为文件名的文本文件
@echo off
for %%i in (??.txt) do echo "%%i"
pausefor /f
for /f 是个十分强大的家伙,如果说for语句是批处理中最强大的语句的话,那么for /f 就是精华中的精华。for /f 的强大和它拥有众多的开关密切相关。因为开关众多所以用法复杂。
# 1.为解析文本而生:for /f 的基本用法
# 所有的对象无论是文件、窗体、还是控件,在所有的非机器语言看来无外乎都是形如"c:\test.txt"、"CWnd"之类的文本信息;而所有的对象具体的如ini文件中的某条配置信息、注册表中的某个键值、数据库中的某条记录……都只有转化为具有一定格式的文本信息,方可被代码识别、操控。可以说,编程的很大一部分工作都是在想方设法绞尽脑汁如何提取这些文本信息。而提取文本信息则是for /f的拿手好戏:读取文件内容、提取某几行字符、截取某个字符片段、对提取到的内容再切分、打乱、杂糅...只要你所能想到的花样for /f 都会想方设法帮你办到,因为for /f 就是被设计成专门用于解析文本的
@echo off
for /f %%i in (test.txt) do echo %%i
pause
# 无论for语句做何种变化它的执行过程仍然遵循基本的for流程:依次处理每个元素,直到所有的元素都被处理为止。只不过在for /f语句中,这里的元素是指文件中的每一行,也就是说,or /f 语句是以行为单位处理文本文件的。这是一条极为重要的规则!!
@echo off
for /f %%i in (test.txt) do echo %%i&pause
pause
# 2. 切分字符串的利器:delims=
# 这里我们引入了一个新的开关:"delims=,",它的含义是:以逗号作为被处理的字符串的分隔符号。
# 在批处理中指定分隔符号的方法是:添加一个形如 "delims=符号列表" 的开关,这样被处理的每行字符串都会被符号列表中罗列出来的符号切分开来
# 需要注意的是:如果没有指定"delims=符号列表"这个开关,那么for /f 语句默认以空格键或跳格键作为分符号
# 例1:下面你会惊奇地发现每行第一个逗号之后的所有内容都不见了(如果有不存在逗号的行,则保留原样)
# 也就说你成功地提取到了每行第一个逗号之前的所有内容!
@echo off
for /f "delims=," %%i in (test.txt) do echo %%i
pause
# 例2:如果我要指定的符号不止一个,该怎么办?你可以一次性指定多个分隔符号!
@echo off
for /f "delims=.," %%i in (test.txt) do echo %%i
pause
# 这样第一个点号或第一个逗号之前的内容都被提取出来了
# 3. 定点提取:tokens=
# 对于 delims= 语法,for /f 默认只能提取到第一节的内容,如果我要提取的内容不在第一节上那怎么办?
# 这时就该轮到 tokens= 出马了!!
# tokens= 后面一般跟的是数字如 tokens=2,也可以跟多个。但是每个数字之间用逗号分隔,如 tokens=3,5,8 它们的含义分别是:提取第2节字符串、提取第3、第5和第8节字符串。
# 注意这里所说的“节”,是由 delims=这一开关划分的,它的内容并不是一成不变的
# 例1:
# 原始文本:尺有所短,寸有所长,学好批处理没商量,考虑问题复杂化,解决问题简洁化。
@echo off
for /f "delims=, tokens=3" %%i in (test.txt) do echo %%i
pause
# 那么要如何接收 tokens= 后面多个数值所指代的内容呢?
# for /f 语句对这种情况做如下规定:
# 如果 tokens= 后面指定了多个数字,如果形式变量为%%i,那么第一个数字指代的内容用第一个形式变量%%i来接收,第二个数字指代的内容用第二个形式变量%%j来接收,第三个数字指代的内容用第三个形式变量%%k来接收…第N个数字指代的内容用第N个形式变量来接收,其中形式变量遵循字母的排序,第N个形式变量具体是什么符号由第一个形式变量来决定:如果第一个形式变量是%%i,那么第二个形式变量就是%%j;如果第一个形式变量用的是%%x,那么第二个形式变量就是%%y。
# 例2:
@echo off
for /f "delims=, tokens=2,5" %%i in (test.txt) do echo %%i %%j
pause
# 这样一个问题:
# 假如要提取的“节”数不是5,而是10或者更多,难道我也得从1写到10或者更多吗?有没有更简洁的写法呢?
# 如果要提取的内容是连续的多“节”的话,那么连续的数字可以只写最小值和最大值,中间用短横连接起来即可!
# 比如 tokens=1,2,3,4,5 可以简写为 tokens=1-5
# 还可以把这个表达式写得更复杂一点:
# tokens=1,2-5,tokens=1-3,4,5,tokens=1-4,5……怎么方便就怎么写吧
# 例3:
@echo off
for /f "delims=, tokens=1,*" %%i in (test.txt) do echo %%i %%j
pause
# tokens=后面所接的星号具备这样的功能:
# 字符串从左往右被切分成紧跟在*之前的数值所表示的节数之后,字符串的其余部分保持不变,整体被*所表示的一个变量接收。
# 4.跳过无关内容,直奔主题:skip=n
# 很多时候有用的信息并不是贯穿文本内容的始终而是位于第N行之后的行内,为了提高文本处理的效率或者不受多余信息的干扰,for /f 允许你跳过这些无用的行,直接从第N行开始处理,这个时候就需要使用参数 skip=n,其中n是一个正整数,表示要跳过的行数
# 例1:这段代码将跳过头两行内容,从第3行起显示test.txt中的信息
@echo off
for /f "skip=2" %%i in (test.txt) do echo %%i
pause
# 5. 忽略以指定字符打头的行:eol=
# 例1:忽略以 `;` 打头的行
@echo off
for /f "eol=;" %%i in (test.txt) do echo %%i
pause
# 我们发现在指定字符的时候只能指定1个字符,指定多了会报错!
# 在很多时候,我对这样的设计颇有微词而又无可奈何:为什么只能指定1个而不是多个?要忽略多个还得又是if又是findstr加管道来多次过滤,那效率实在太低下了——能用到的功能基本上都提供,但是却又做不到更好,批处理,你的功能为什么那么弱?
# 此外它还有一个特性:
# for /f 语句是默认忽略以分号打头的行内容的,正如它默认以空格键或跳格键作为字符串的切分字符一样
# 6. 如何决定该使用 for /f 的哪种句式?(兼谈)
# for /f %%i in (……) do (……) 语句有好几种变形语句,不同之处在于第一个括号里的内容:有的是用单引号括起来,有的是用双引号包住,有的不用任何符号包裹,具体格式为:
1、for /f %%i in (文件名) do (……)
2、for /f %%i in ('命令语句') do (……)
3、for /f %%i in ("字符串") do (……)
# 原则:
# 1、当希望读取文本文件中的内容的话,第一个括号中不用任何符号包裹,应该使用的是第1条语句;例如:你想显示test.txt中的内容,那么,就使用 for /f %%i in (test.txt) do echo %%i;
# 2、当你读取的是命令语句执行结果中的内容的话,第一个括号中的命令语句必须使用单引号包裹,应该使用的是第2条语句;例如:你想显示当前目录下文件名中含有test字符串的文本文件的时候,应该使用for /f %%i in ('dir /a-d /b *test*.txt') do echo %%i 这样的语句;
# 3、当你要处理的是一个字符串的时候,第一个括号中的内容必须用双引号括起来,应该是用的是第3条语句;例如:当你想把bbs.bathome.cn这串字符中的点号换为短横线并显示出来的话,可以使用for /f "delims=. tokens=1-3" %%i in ("bbs.bathome.cn") do echo %%i-%%j-%%k 这样的语句。
# 一个十分头痛的问题:在第1条语句中,如果文件名中含有空格或&,该怎么办?照旧吗?
# 例子:屏幕上出现了可耻的报错信息:系统找不到文件 test
@echo off
for /f %%i in (test 1.txt) do echo %%i
pause
# 你一拍大腿,猛然想起了一件事:当路径中含有特殊字符的时候,应该使用引号把路径括起来。对,就是它了!但是当你把代码写出来之后,你很快就焉了:for /f %%i in ("test 1.txt") do echo %%i,这不就是上面提到的第3条 for /f 命令的格式吗?批处理会把 test 1.txt 这个文件名识别为字符串啊!
# 解决方法见7
# 7. usebackq的使用
# 这时候usebackq就派上用场了,usebackq 是一个增强型参数。当使用了这个参数之后原来的for语句中第一个括号内的写法要做如下变动:
# 如果第一个括号里的对象是一条命令语句的话,原来的单引号'要改为后引号`
# 如果第一个括号里的对象是字符串的话,原来的双引号"要改为单引号'
# 如果第一个括号里的对象是文件名的话,要用双引号"括起来
@echo off
for /f "usebackq" %%i in ("test 1.txt") do echo %%i
pausefor /d 查询目录
# 格式:
FOR /D %%variable IN (set) DO command [command-parameters]
# 注意项:
# 1.这个参数主要用于目录搜索,不会搜索文件。
# 2.只能搜索指定目录和缺省情况当前目录下的目录名字,不搜索子目录。
# 例1:执行后会把C盘根目录下的全部目录名字打印出来,而文件则不显示!
@echo off
for /d %%i in (c:\*) do echo %%i
pause
# 例2:删除当前目录下的文件夹,但不会删除文件
@echo off
for /d %%i in (*)do rd /s /q "%%i"
pausefor /r 遍历搜索
# 格式:
FOR /R [[drive:]path] %%variable IN (set) DO command [command-parameters]
# 用法:
# 检查以 [drive:]path 为根的目录树,指向每个目录中的 FOR 语句
# 如果在 /R 后没有指定目录,则使用当前目录
# 如果集仅为一个单点(.)字符,则枚举该目录树
# 这个R可以理解为recursive的缩写也就是递归的意思
# 前面我们知道,/d 搜索的是目录名字,那么现在这个/r 则是搜索当前或者你指定路径下的文件名字。
# 注意项1:
# set 中的文件名如果含有通配符(?或*)
# 则列举/R 参数指定的目录及其下面的所有子目录中与 set 相符合的所有文件,无相符文件的目录则不列举
# 例1:把这个 BAT 保存到 D 盘随便哪里然后执行,就会看到它把 C 盘根目录和每个目录的子目录下面全部的EXE 文件都列出来了!
@echo off
for /r c:\ %%i in (*.exe) do echo %%i
pause
# 例2:这个命令前面没加那个 c:\ (也就是搜索路径),这样它就会以当前目录为搜索路径,比如你这个 BAT放在 d:\test目录下执行,那么它就会把 d:\test 目录和它下面的子目录的全部EXE 文件列出来!!!
@echo off
for /r %%i in (*.exe) do echo %%i
pause
# 注意项2:如果 set 中为具体文件名不含通配符,则枚举该目录树(即列举该目录及其下面的所有子目录),而不管set 中的指定文件是否存在。这与前面所说的单点(.)枚举目录树是一个道理,单点代表当前目录也可视为一个文件。
# 例1:执行后,它不管boot.ini是否存在而将枚举c 盘所有目录。
# 为了只列举 boot.ini 存在的目录,我们可改成例2
@echo off
for /r c:\ %%i in (boot.ini) do echo %%i
pause
# 例2:
@echo off
for /r c:\ %%i in (boot.ini) do if exist %%i echo %%i
pausefor /l 建立序列
# 格式:
FOR /L %%variable IN (start,step,end) DO command [command-parameters]
# 该语句中(start,step,end)表示以增量或者递减形式从开始到结束的一个数字序列。
# 因此 (1,1,5)将产生序列1 2 3 4 5 , (5,-1,1) 将产生序列5 4 3 2 1
# /l参数将对start与end两个数值进行比较来执行迭代变量,如果star小于end,就会执行该命令。
# 如果迭代变量超过end值,则命令解释程序退出此循环。
# 例1:打印从 1 2 3 4 5这样5 个数字,而且每个数字占一行
@echo off
for /l %%i in (1,1,5) do echo %%i
pause环境变量延迟
什么是延迟环境变量扩展
延迟变量全称 "延迟环境变量扩展" ,要理解这个东西,我们还得先理解一下什么叫变量扩展!CMD在解释我们的命令的时候首先会读取一条完整的命令,然后对其进行一些命令格式的匹配操作,看你所输入的命令格式是不是符合它的要求。如果我们要在命令中引用一些变量,那么我们如何让CMD在解释我们的命令时能识别出这个变量呢?这时我们就可以在变量名字两边加一个%号如%name%。当CMD在读取我们的整条命令进行格式匹配的时候就会发现name这个字符两边加了%号,就不会把它当作普通字符处理而是会把它当作一个变量,处理变量名叫name然后CMD就会找到变量名对应的值,用该值替换掉这个变量名字(name)(如果变量名不存在值就返回空值)。再将这个替换好并且匹配的命令执行!这个替换值的过程就叫做变量扩展。说白了就是把变量的名字用它的值给替换掉后执行!也就是批处理如何识别一个变量的过程(注意:这里只是变量的扩展的意思,不是延迟环境变量扩展,要理解延迟环境变量扩展必须先理解什么是变量的扩展) 也就是批处理如何识别一个变量的过程。
@echo off
set var=test
echo %var%
pauseCMD在读取到 echo %var% 这句命令后就会进行匹配操作,它马上就发现var字符两边有%号。这时CMD就会把它当作一个变量处理,查看这个var变量名是不是有值,如果有就用该值把变量名var给替换掉。这里我们的var在上一条命令set var=test中给var赋值为test,所以CMD会用test把%var%这个变量名替换掉替换后的结果就为echo test了。这些步骤都是CMD进行匹配操作的步骤,匹配完后它再执行echo test这条语句。这时我们的CMD中就会echo出一个test了
什么是环境变量扩展知道了,那什么是延迟环境变量扩展呢?在理解环境变量扩展时我们知道CMD在解释命令时首先会把一条完整的命令进行读取,然后进行匹配操作。匹配时它会把命令里的变量用变量的值给替换掉然后执行这个替换好的命令。问题就出在"一条完整的命令",在BAT中,IF FOR这样的命令都可以加括号,将一些命令嵌套在里面执行,这样的话对于一条可以加扩号嵌其他命令的命令,他的完整格式就是for %%i in (....)这样一个整体。此时如果我们如果在括号里面嵌入一些设置变量值的命令,就会出现问题了!
@echo off
for /l %%i in (1,1,5) do (
set var=%%i
echo %var%
)
pause执行后会显示5个空行的错误提示!为什么?根据我们上面说的知识来理解。
通过这两个例子大家应该已经理解,如果只有环境变量扩展这个过程的话,如果我们在可以嵌套命令的命令中执行 赋值操作时会让我们的BAT出现给变量赋值的问题。那么这个时候"延迟环境变量扩展"这个概念就被提出来了。在批处理中我们可以用 setloacl enabledelayedexpansion 这个命令来启用"延迟环境变量扩展" ,在我们启用了"延迟环境变量扩展"后,当CMD在解释含有嵌套格式的命令时会把嵌套的命令一条一条的先执行一次,然后再进行匹配操作,这样我们的赋值操作就会完成。且在"延迟环境变量扩展"启用后,CMD会用!号来判断这是不是一个变量 。如没启用前变量用 %name% 这样的格式判断,启用后就用 !name! 这样的格式判断了,这个符号我们需要注意!
@echo off
setlocal enabledelayedexpansion
set var=1
for /l %%i in (1,1,5) do (
set /a var =%%i
echo !var!
)
pause批处理变量延迟详解
关于环境变量延迟扩展使用set /?可以查看到部分说明,不过考虑到其粗劣的翻译水平建议在查看之前首先chcp 437切换为英文查看原英文说明。鉴于文中已说得十分详尽而且有数个代码示例应该不难理解。在此仅略作一些补充。
在许多可见的官方文档中均将使用一对百分号闭合环境变量以完成对其值的替换行为称之为“扩展(expansion )”,这其实是一个第一方的概念,是从命令解释器的角度进行称谓的,而从我们使用者的角度来看,则可以将它看作是引用(Reference)、调用(Call)或者获取(Get)。
而命令解释器是扩展环境变量的行为大致如下:首先读取命令行的一条完整语句,在进行一些先期的预处理之后,命令被解释执行之前会对其中用百分号闭合的字符串进行匹配,如果在环境空间中找到了与字符串相匹配的环境变量则用其值替换掉原字符串及百分号本身,如果未得到匹配则用一个空串替换,这个过程就是环境变量的“扩展”,它仍然属于命令行的预处理范畴。
而一条“完整的语句”在NT的命令解释器CMD中被解释为“for if else”等含有语句块的语句和用“& | && ||”等连接起来的复合语句。因此当CMD读取for语句时,其后用一对圆扩号闭合的所有语句将一同读取,并完成必要的预处理工作,这其中就包括环境变量的扩展,所以在for中的所有语句执行之前,所有的环境变量都已经被替换为for之前所设定的值,从而成为一个字符串常量而不再是变量。无论在for中将那些环境变量如何修改,真正受到影响的只是环境变量空间,而非for语句内部。
而为了能够在for语句内部感知环境变量的动态变化,CMD设计了延迟的环境变量扩展特性,也就是说当CMD读取了一条完整的语句之后,它不会立即执行变量的扩展行为,而会在某个单条语句执行之前再进行扩展,也就是说这个扩展行为被“延迟”了。
延迟环境变量扩展特性在CMD中缺省是关闭的,开启它的方法目前有两个:
- 一是CMD /v:off(此处说法有误,应为 CMD /v:on——namejm 注),它会打开一个新的命令行外壳,在使用exit退出这个外壳之前,扩展特性始终有效,常用于命令行环境中;
- 二是setlocal EnableDelayedExpansion,它会使环境变量的修改限制到局部空间中,在endlocal之后,扩展特性和之前对环境变量的修改将一同消失,常用于批处理语句中。
本例启用了变量延迟,是个正确的例子!
@echo off & setlocal EnableDelayedExpansion # 关闭命令回显,并启用变量延迟
for /f "tokens=* delims=" %%i in ("Hello world.") do (
set n=%%i
set n=!n:ld.=t!
set n=!n:o w= S!
set n=!n:He=Wi!
echo !n!
)
Pause下面来看一个错误的例子
@echo off
for /f "tokens=* delims=" %%i in ("Hello world.") do (
set n=%%i
set n=%n:ld.=t%
set n=%n:o w= S%
set n=%n:He=Wi%
echo %n%
)
Pause这和前面的例子差不多只是所有!号都换成%号,这是个错误的例子。
因为它没有启用变量延迟也没有使用!号把变量括起来。
我们看到它的执行结果是显示“ECHO 处于关闭状态”。为什么会这样呢?
原因是在没有启用变量延迟的情况下,凡是在括号内(即do里面)的变量,在执行for语句之前就已经被替换成for语句之前其它命令对该变量所赋予的值。
则是说在本例中的以下几句
set n=%%i
set n=%n:ld.=t%
set n=%n:o w= S%
set n=%n:He=Wi%
echo %n%第一句能正常执行并达到它的目的,因为它只是单纯地将%%i的值赋予给变量n所以没有任何问题。
其它几句属于这样情况:早在for语句执行前CMD就急不切待地将这几句里面的所有变量n一同执行替换行为,替换为for之前,其它命令对n所设置的值从而使n变成一个常量。但在本例中for语句之前只有@echo off这句,并没有其它命令对n作过任何赋值行为,所以在for之前变量n的值为空值。
即是说set n=%n:ld.=t% 这句里面的变量n,在CMD读取(注意是读取不是执行)完整个for语句后(这时还未轮
到set执行自己的任务),就立刻被替换为一个空值,一个空值里面没有任何东西所以就不存在一字符替换另一字
符这种说法(没有东西怎么替换?)。
最终到执行set n=%n:ld.=t%语句时,它只是获取一个空值,再给变量n赋予空值而已。其它几句也是一样原理。
所以最后echo %n%的时候变量n还是个空值,而echo命令没有东西可以显示就只有显示“ECHO 处于关闭状态这句来说明自己的状态。
通过这个例子的说明已经能说明变量延迟的作用!我们再回头来看看例1,启用变量延迟后在执行
set n=!n:ld.=t!
set n=!n:o w= S!
set n=!n:He=Wi!
echo !n!这些语句前,它们里面的变量n不会马上被CMD替换(启用延迟后,CMD变得有耐性啦_),而未被替换的话,那么n就还是变量而不是常量。等到执行set n=!n:ld.=t!等这几句时变量n才被替换。这样每个set命令都能感知变量
n的任何变化从而作出正确的替换行为。这就是变量延迟啦!
不要以为只有for才要用变量延迟,下面这个例子同样需要
这是个错误的例子:
@echo off
set mm=girl & echo %mm%
pause执行后依然显示“ECHO 处于关闭状态”。 原因是没有启用延迟,而且在set mm=girl & echo %mm% 语句前没有其它命令对mm进行赋值。这时当CMD执行set mm=girl & echo %mm%语句前就已经急不切待地把变量mm的值替换了,而又因为前面没给mm赋值,所以mm被替换为空值变成常量。等到echo命令执行时它其实是echo一个不会变化的常量,本例中即是空值。
正确写法:
@echo off&setlocal EnableDelayedExpansion
set mm=girl&echo !mm!
pause延迟变量使用时机
什么时候使用延迟变量?如何使用?这些一直是使新手困惑的地方,那到底是怎么样的呢?那请看下面的例子
例1:
@echo off
set /a num=0
for /l %%i in (1 1 3) do (
Rem ================================
set /a num =1
Rem 原意是变量num的值每次都加1
Rem ================================
echo %num%
)
pause>nul先猜猜看运行之后的结果是什么呢?你是不是认为它会显示:1 2 3 呢?我想大部分人会这么认为。你再将以
上代码保存为批处理文件运行看看结果。你会看到显示的结果并不是意料中的 1 2 3 而是 0 0 0,这个是为什么呢?
原来这个是因为批处理在处理for 或者if 语句中的变量时先要进行预处理,把其中的用%%括起来的变量先
替换为语句之前的变量(如上面的代码,for语句中的%num%早就被替换为语句前的值:0),所以for语句运行时虽然已经给变量加了1,但是值却不变(因为echo %num%中的%num%早已被替换为:0了)。
那么要实现(for或者if)语句中的变量实时的变化(如这里我就要将1 2 3 显示出来)要怎么办呢?那就要起
用延迟变量,先在批处理中申明:setlocal enabledelayedexpansion 然后将语句:echo %num%改成!num!(也就是将“%”改成“!”),这样就可以达到效果了,演示代码:
@echo off
Rem ''''///////下面先申明起用延迟变量/////////////
setlocal enabledelayedexpansion
set /a num=0
for /l %%i in (1 1 3) do (
Rem ================================
set /a num =1
Rem 变量num的值每次都加1
Rem ================================
Rem '''''''//////////////////下面的变量不能再用"%"括起来,而应该用"!"////////////
echo !num!
)
pause>nul归纳总结:
1、为什么要用延迟变量?
==> 让if语句和for语句中的变量实时变化
2、什么时候用延迟变量?
==> 一般是用在 for 语句和 if 语句中
3、怎么用延迟变量?
==> 先在批处理中申明起用延迟变量:setlocal enabledelayedexpansion,然后将 for 语句、if语句中的变量用两个"!"括起来即可
4、其实在使用变量嵌套变量也可以使用变量延迟的