-------siwuxie095
for 语句很强大,配合 if、call、goto 等流程控制语句,更是可以实现
脚本复杂的自动化、智能化操作,离开了 for 语句,很多事情都办不了
但是 for 命令是如此之复杂,学习 for 语句很艰难,假如想通过
帮助命令里的信息来学习 for 语句,会让人感到绝望!能否熟练
充分使用 for 命令,是高手与低手的分水岭,下面将 for 语句彻
底拆解!
首先是帮助信息:
FOR
对一组文件中的每一个文件执行某个特定命令
标准格式:FOR %%variable IN (set) DO command [command-parameters]
更详细的语法:
FOR [-d | -r | -l | -f] %%variable IN (set) DO command [command-parameters]
中文"翻译":
FOR [-d | -r | -l | -f] %%变量名 IN (相关文件或命令) DO [执行命令]
这里用 %%,两个百分号是批处理文本中书写的格式,如果是用户在
命令行输入的形式,只需一个 % 号
注解:
for 有四个参数: /d /r /l /f
%%变量名:变量名可以是单个的大小写字母(区分大小写),for 会把
从 (set) 读取到的每个值按顺序赋值给它
in: 命令格式,默认即可
(相关文件或命令): for 把这里的值读取后赋值给变量 %%variable
do: 命令格式,默认即可
执行命令: 对每个变量的值要执行的操作,当然也可以没有任何操作,这个看
实际需要。例如利用 for 循环来延迟程序,就不需要 for 执行任何操作,只需
要不断循环即可
参数详解:
for 没有任何开关的情况:
for %%i in (*) do echo %%i
这条命令的变量 %%i 取值 *,而不是取具体值,表示特殊
含义,即显示当前目录下,所有非文件夹的文件名字(包
括 .rar .jpg .exe .bat .sys 等所有非文件夹)
@echo off for %%i in (*) do echo %%i pause |
sublime中:
运行一览:当前目录下只有 test.bat 本身这一个文件(非文件夹)
若 %%i 取具体的值,即表示分别取列出来的具体的值:
for %%i in (a, b c,d,e) do echo %%i
@echo off for %%i in (a, b c,d;e) do echo %%i pause |
sublime中:
运行一览:
显然:空格、逗号和分号都可以作为分隔符。一般情况下,都用
逗号作为分隔符,尤其在数据是数字的情况下更具有可读性。
利用这个特点可以将变量 %%i 取一些不连续的值。
例如要将变量分别取值为 1、1945、1949、2008、2012 五个值,
由于变量之间不是等差数列关系,用 for /l %%i in () do () 循环的
形式无法达到目的。
这样写即可:
for %%i in (1,1945,1949,2008,2012) do echo %%i |
输出字母表:
因为批处理不可以直接转换为 ASCII 值,所以比 C 语
言麻烦。在批处理里,用 for 输出字母表最简洁
@echo off for %%i in (a b c d e f g h i j k l m n o p q r s t u v w x y z) do echo %%i pause |
或:
@echo off set var=a b c d e f g h i j k l m n o p q r s t u v w x y z for %%i in (%var%) do echo %%i pause |
/d
只搜索当前目录下的目录(也就是文件夹 ,不包括子目录)
注意:/d 无法搜索到隐藏的文件夹
语法:
for /d %%variable in (set) do command [command-parameters]
搜索 set(可以包含通配符 * 和 ?)里的文件夹后执行指定的
Command。用于目录搜索,不会搜索文件。
通配符 * 和 ?的区别:
* 表示任意 n 个字符,用一个 * 符号足以。而 ?表示任意一个字符,
当要表达"不多于 k 个字符的文件夹",就要写上 k 个 ?,对于文件
夹命名中的中文(任意个),算作 0 个字符
例如:??? 三个问号,不仅代表有三个字母的文件夹,还包括一个
字母的文件夹和两个字母的文件夹,都会被搜索出来
如:
@echo off for /d %%i in (F:*) do echo %%i pause |
sublime中:
运行一览:
/d 不能显示文件名字,只能显示目录。说白了就是显示
该目录下的所有文件夹名字
再如:
"program files" 含有空格,必须用双引号,否则出错
@echo off for /d %%i in (C:"program files"*) do echo %%i pause |
sublime中:
运行一览:将 C:program files 里面的所有文件夹都显示出来
再如:
@echo off for /d %%i in (???) do echo %%i pause |
sublime中:
运行一览:把这个批处理程序放在哪里运行,
程序会把当前路径下名字只有 1~3 个字母的
文件夹显示出来 ,没有就不显示
(这是在桌面的运行结果)
再如:指定搜索路径
@echo off for /d %%i in (C:windows????) do echo %%i pause |
sublime中:
运行一览:
for /d 不能匹配带隐藏属性的文件夹,在灵活性上不及 for /f 和 dir 的组合;
当 "元素集合"中不包含任何通配符时,完全是 "for %%i in (元素集合) do …"
语句的翻版,但又稍显复杂。感觉 for /d 很鸡肋
/r
只搜索目录中(包括子目录和子目录的子目录,也就是目录树)的所
有文件。这个和 /d 作用互补
语法格式:
FOR /R [[drive:]path] %%variable IN (set) DO command [command-parameters]
如果在 /r 后没有指定目录,则使用当前目录。如果 set 仅为一个单点(.)字符,
则枚举该目录树。
例如:for /r C:windows %%i in (.) do echo %%i 枚举 C:windows 目录树的
所有文件。
/r 可以把当前或指定路径下的文件名字全部读取,注意是文件名
字。
注意两点:
a、set 中的文件名如果含有通配符( ? 或 * ),则列举 /r 参数指定的目录
及其下面的所用子目录中的与 set 相符合的所有文件,无相符文件的目录
则不列举。
b、相反,如果 set 中为具体文件名,不含通配符,则枚举该目录树(即
列举该目录及其下面的所有子目录),而不管 set 中的指定文件是否存在。
这与前面所说的单点( . )枚举目录是一个道理,单点代表当前目录,也可
视为一个文件
如:将 C盘根目录及其子目录下的所有 exe 文件显示出来
@echo off for /r c: %%i in (*.exe) do (echo %%i & pause > nul) pause |
sublime中:
再如:没有指定搜索路径,则默认
当前目录为搜索路径
@echo off for /r %%i in (*.exe) do @echo %%i pause |
再如:
@echo off for /r C: %%i in (bootres.dll) do echo %%i pause |
运行后会列举C盘所有目录,且每个目录都会显示 bootres.dll,
但实际上并不是真的存在 bootres.dll,只是计算机在搜索所有
目录时伴随回显罢了
若要只列举 bootres.dll 存在的目录:
@echo off for /r C: %%i in (bootres.dll) do if exist %%i echo %%i pause |
运行一览:win 10下存在 bootres.dll,其他系统未知
若要对获取到的路径做进一步处理,则需要把 dir 语句放入 for /f 语句
中进行分析,写成 for /f %%i in ('dir /ad /b /s') do … 的形式;
由于 for /r 语句是边列举路径边进行处理,所以,在处理大量路径时,
前期不会感到有停顿,而 for /f 语句则需要等到 dir /ad /b /s 语句把
所有路径都列举完之后,再读入内存进行处理,所以,在处理大量路径
时,前期会感到有明显的停顿
当列举目录时,for /r 和 dir /ad /b /s 的效果非常类似,当要获取
目录路径并做进一步处理的时候,两者之间,该如何选择?
a、for /r:
优点:
① 只通过 1 条语句就可以同时实现获取目录路径
和处理目录路径 2个操作;
② 遍历文件夹时,边列举边处理,获取到一条路径
就处理一条路径,内存占用小,处理大量路径时不会
产生停顿感;
缺点:
① 不能获取到带隐藏属性的目录,产生遗漏;
② 不能获取带指定属性的目录;
b、dir /ad /b /s:
优点:
① 能一次性获取带任意属性的目录,不会产生遗漏;
② 能通过指定不同的参数获取带任意属性的目录,更具灵活性;
缺点:
① dir /ad /b /s 仅能获取到目录路径,若要实现进一步的处理,
还需要嵌入 for /f 语句中才能实现,写法不够简洁;
② 嵌入 for /f 语句之后,需要写成 for /f "delims=" %%i in
('dir /ad /b /s') do … 的格式,受 for /f 语句运行机制的制约,
需要先列举完所有的路径放入内存之后,才能对每一条路径做
进一步的处理,处理大量路径时,内存占用量偏大,并且在前
期会产生明显的停顿感,用户体验度不够好;
综上,可做出如下选择:
a、若仅仅是为了获取某文件夹及其所有子文件夹的路径的话,
选择 dir /ad /b /s 语句;
b、若需要过滤带隐藏属性的文件夹,for /r 和 dir 语句都可以
实现,但 for /r 内存占用小,处理速度快,是上上之选;
c、若需要获取所有文件夹,则除了 dir /ad /b /s 外,别无选择,
因为 for /r 语句会遗漏带隐藏属性的文件夹
/l
语法格式:
FOR /L %%variable IN (start,step,end) DO command [command-parameters]
从 start 开始,以 step 为步长,直至最接近 end 那个整数为止,中间有
多少个整数,do 后面就执行多少次
(1,1,5)将产生序列 12345,5 次重复,并依次将序列赋值到变量 %%i
(5,-1,1)将产生 54321 序列,5 次重复,并依次将序列赋值到变量 %%i
常用于循环结构,对于 in 后面括号里的三个变量 ,逗号隔开
改为空格隔开也可,不过不建议用空格隔开
如:竖着显示 12345
@echo off for /l %%i in (1,1,5) do echo %%i pause |
如:打开 5 个 cmd 窗口
@echo off for /l %%i in (1,1,5) do start cmd pause |
注意:在循环里,不能改变循环变量的值!对循环上下限变量
允许计算,但不会影响循环次数
如:循环变量 %%i 的值不变
@echo off setlocal enabledelayedexpansion for /l %%i in (1,1,10) do ( set %%i+=10 echo %%i ) pause |
如:上下限的值变了,循环次数不变
@echo off setlocal enabledelayedexpansion set /a min=1,max=10 for /l %%i in (!min!,1,!max!) do ( echo min=!min! max=!max! set /a min+=1 set /a max*=2 ) pause |
for 里的循环变量 %%i 和参数 %0 - %9,就代表它是变量,
在引用时,不可以再对其增加变量符号,即%%%i% 、!%%i!、
%%1%、!%1! 等形式都不可以
循环结构的选择 for 还是 goto?
当循环次数确定时,首选 for /l 语句,代码简单明了,也可
使用 goto 语句但不推荐;
当循环次数不确定时,用 goto 语句将是唯一的选择,此时
需要用 if 之类的条件语句来判断何时结束 goto 跳转
无限循环:
for /l %%i in () do echo Hello
@echo off for /l %%i in () do echo Hello pause |
【made by siwuxie095】