BAT批处理⽂件for命令详解
Windows bat脚本的for语句基本形态如下:
在cmd窗⼝中:for %I in (command1) do command2
在批处理⽂件中:for %%I in (command1) do command2
之所以要区分cmd窗⼝和批处理⽂件两种环境,是因为在这两种环境下,命令语句表现出来的⾏为虽然基本⼀样,但是在细节上还是稍有不同,最明显的⼀个差异就是:在cmd窗⼝中,for之后的形式变量I必须使⽤单百分号引⽤,即%I;⽽在批处理⽂件中,引⽤形式变量I必须使⽤双百分号,即%%I。为了⽅便起见,若不是特别强调,以下的讲解都以批处理⽂件环境为例。
我们先来看⼀下for语句的基本要素都有些什么:
for、in和do是for语句的关键字,它们三个缺⼀不可;
%%I是for语句中对形式变量的引⽤,即使变量l在do后的语句中没有参与语句的执⾏,也是必须出现的;
in之后,do之前的括号不能省略;
command1表⽰字符串或变量,command2表⽰字符串、变量或命令语句;
1.FOR
对⼀组⽂件中的每⼀个⽂件执⾏某个特定命令。
FOR %variable IN (set) DO command [command-parameters]
%variable 指定⼀个单⼀字母可替换的参数。
(set) 指定⼀个或⼀组⽂件。可以使⽤通配符。
command 指定对每个⽂件执⾏的命令。
command-parameters
为特定命令指定参数或命令⾏开关。
例:
@echo off
for %%i in (*.txt) do echo %%i
pause>nul
这段代码会显⽰当前⽂件夹下所有的txt⽂件
@echo off
for %%i in (菜芽⼩公公) do echo %%i
pause>nul
这段代码会显⽰
菜
芽
⼩
公
公
注:%%i为for输出专⽤变量格式,其中i可以是a/A/0-z/Z/9和⼀些符号什么的(如! # 不过不建议使⽤),在cmd中只能⽤⼀个%
2.FOR /L
FOR /L %variable IN (start,step,end) DO command [command-parameters]
该集表⽰以增量形式从开始到结束的⼀个数字序列。
因此,(1,1,5) 将产⽣序列 1 2 3 4 5,(5,-1,1) 将产⽣
序列 (5 4 3 2 1)。
例:
@echo off
for /L %%a in (1 2 1000) do echo %%a
pause>nul
这个⽤法很简单,没有什么要讲解的,从这段代码主要是看出了逗号可以省略.
3.FOR /R
FOR /R [[drive:]path] %variable IN (set) DO command [command-parameters]
检查以 [drive:]path 为根的⽬录树,指向每个⽬录中的
FOR 语句。如果在 /R 后没有指定⽬录,则使⽤当前
⽬录。如果集仅为⼀个单点(.)字符,则枚举该⽬录树。
这个命令同样有⼀些看起来很奇怪的⽤法,为了防⽌新⼿迷糊就只讲解基础的
例:
@echo off
for /r C:\Windwos\system32 %%i in (*) do echo %%i
pause>nul
这段代码枚举了C:\Windows\system32下所有的⽂件,包括⼦⽂件夹⾥的
@echo off
setlocal enabledelayedexpansion
FOR /R d: %%i IN (.) DO (
set dd=%%i
set "dd=!dd:~0,-1!"
echo !dd!
)
pause
exit
上例即可以罗列出D盘下的所有⽂件夹,其速度要⽐命令"tree d:"慢多了,不过其返回结果的实⽤性则远远超过了tree命令。
⼀般情况下我们不推荐通过遍历⽂件夹来查⽂件,特别是在查某些程序(⽐如QQ.exe)的位置时。推荐通过reg命令查注册表来查QQ的路径,以保证查效率。
上例中也出现了⼏个新⾯孔,如setlocal、感叹号等。其中,感叹号其实就是变量百分号(%)的强化版。之所以要⽤!⽽不⽤%,是因为在for循环中,当⼀个变量被多次赋值时,%dd%所获取的仅仅是dd第⼀次被赋予的值;要想刷新dd的值,就必须⾸先通过命令"setlocal enabledelayedexpansion"来开启延迟变量开关,然后⽤!dd!来获取dd的值。
4.FOR /D
FOR /D %variable IN (set) DO command [command-parameters]
如果集中包含通配符,则指定与⽬录名匹配,⽽不与⽂件
名匹配。
这个命令的⽤法和上⾯差不多,只不过是枚举⽬录名,不详解了
5.FOR /F
这个参数/f将会打开(集)⾥的⽂件,使for命令能处理⽂本⽂件的读取和添加删除替换等编辑性的操作,可谓功能强⼤,因此也相对复杂⼀些。
⽂件名-集
for /f “选项” %变量 in ( “字符串”-集 ) do 命令 ‘命令’-集
/f 后可以带有⼏种选项,不带选项当然也是合格的格式,⽽带有参数则必须以引号整体括起来,后⾯的集⾥主要由三种形式形成的,最终在for循环中的每⼀轮中会形成读取⼀⾏字符串,来给指定的%变量、以及给由于选项中派⽣出附加变量赋值后,执⾏do后⾯的命令
下⾯以例⼦来具体说明和逐步理解各分项的⽤法
例6
假定d:\内容如下:
姓名 性别 年龄 等-级
张三 男 36 A-1
李四 男 29 B-2
赵六 ⼥ 31 A-2
执⾏如下命令:
for /f %c in (d:\) do @echo %c
则屏幕上显⽰:
姓名
张三
李四
赵六
解释:这是for /r 在“%变量”前缺省参数选项时的情况,循环中每轮会默认以空格为分隔,在打开的⽂件中逐⾏给字符串分段,⼜因为没给增添附加变量(即仅⼀个变量%c)则仅把第⼀段的字符赋给%c,再执⾏ do后的命令,然后进⾏循环的下⼀轮,并且默认忽略空⾏
改⼀下:
for /f “skip=1 tokens=1,4 delims= ” %c in (d:\) do @echo %c %d
显⽰为:
张三 A-1
李四 B-2
赵六 A-2
解:
skip
skip=1 表⽰⽂本开始忽略的⾏数为1 ——忽略⼏⾏
tokens
tokens=1,4 这个等号后的数字表⽰依次取第⼏个被分隔的字符串段,来分别赋给%变量及顺序附加的
变量,本例取第1个段赋给%c,第4个段赋给c后的⼀个变量也就是赋给%d,并且,可以写成tokens=1,2,5-7 或tokens=1,2,3* 或tokens=1,2,5,7 分别表⽰取第
1,2,5,6,7(依次赋给%c, %d, %e, %,f, %g共5个变量)、1,2,3及3后的所有段(要赋给3个变量)、1,2,5,7(要赋给4个变量),tokens=后的数字号可以不按顺序,但书写的顺序与分配给变量的顺序是对应的,这是赋值,⾄于之后do命令中⽤不⽤是另⼀回事。换句话 --——最多只需取哪⼏段
in (变量) 中的那个变量,代表起始的⼀个变量名,按tokens中定义的总个数来扩充附加变量名,如总个数为3,则%c 就附加%d和%e ,要是%C就附加%D%E… 本例中tokens=1,4仅需两个,起始的是in () 括号中的%c 则每⾏中第⼀段赋给%c,第4段赋给变量%d
以第⼆⾏(第⼀⾏被skip=1跳过了)为例,在 “张三 男 36 A-1 ” 中(正好也是⽤的空格分隔)共被空格之⼑切为五段,只要第1、4,即张三赋给%c, A-1赋给%d,执⾏@echo %c %d然后下⼀轮…⽽空⾏照旧被省去了。
再稍改⼀下:
for /f “skip=1 tokens=4,1 delims=- “ %c in (d:\) do @echo %c %d
则显⽰为:
A 张三
B 李四
A 赵六
delims
delims在⼀⾏中,⽤什么单个符号(可以有多字符组合,之间也不能加空格,被理解为多项单个字符,如要空格符须放最后)来分隔字符串作为读取赋值的单元(形成⼀段),本例中等号后是空的表⽰仅⽤空格来分隔。——⽤什么⼑来切分
例:⽂本“静夜思.txt”的内容是:
床前明⽉光,疑是地上霜,举头望明⽉,低头思故乡。
⽂本中有四句古诗,诗句之间⽤逗号分隔。古诗原本是没有标点符号的,标点符号是后⼈才加上去的。逗号在语⽂上是语⽓暂停的意思,其实就是⽤来分隔语句意思以便于阅读和理解。
Delims=,的意思就是提取逗号做分隔符,并以此将诗句分成四个⼩列或⼩节。
如果我要⽤for将四句诗都显⽰到屏幕上,不需要任何参数即能实现:
@echo off
for /f %%i in (静夜思.txt) do echo %%i
pause>nul
如果我只要“床前明⽉光”这句话,就需要delims帮忙了:
@echo off
for /f "delims=," %%i in (静夜思.txt) do echo %%i
pause>nul
讲解:
delims=后⾯跟了⼀个逗号,表⽰⽤原⽂中的逗号作为分隔符(划分的⽅法)将古诗分成四个⼩节。默认情况下,delims只显⽰分隔符前的第⼀⼩节,分隔符通常被忽略掉。显⽰其他⼩节的诗句要⽤到列提取命令“tokens”。
例:如何只显⽰每⾏的第⼀个标点前的内容?
@echo off
for /f "eol=: delims=,, " %%i in (静夜思.txt) do echo %%i
pause>nul
运⾏结果显⽰:
注意:
⽂本中有英⽂的点号和中⽂的逗号,点号要放在逗号前⾯。
符号集中(也就是=后⾯的标点符号),各个符号之间没有空格。
⽂本中⽤空格分隔的,符号集⾥中⽂逗号后⾯只有⼀个空格,且必须放到最后。
⽤于分隔的标点符号重复的⼀般只取⼀个做代表。
for默认是以空格和,:;/等标点符号作分割符的,所以要取得整⾏内容通常会⽤"delims="这样的形式来取消for的默认分割符。
默认情况下,也就是没有即使没有⽤delims选项,for也会以空格作为分隔符,将空格后的内容屏蔽掉。
使⽤delims的⽬的主要是通过切分字符串获得可编辑的字符串以便于进⾏下⼀步编辑。Delims好⽐⼀把西⽠⼑,⽂本信息就好⽐西⽠,使⽤delims这把西⽠⼑将⽂本这个西⽠切分成许多⼩块,这样吃起来就⽅便了。
如果你想吃其中的某⼀块,怎么办呢?直接⽤⼑叉tokens提取就可以了。
例
假定d:\aa.txt内容如下:
Volume in drive D is MYDA
Volume Serial Number is C35D-8998
Directory of D:tmp
09/25/2001 10:40 AM 11,
11/12/2001 04:29 pM
04/11/2002 04:18 AM 2,
3File(s) 12,673 bytes
0 Dir(s) 5,020,200,655 bytes free
在命令⾏输⼊:
for /f "skip=5 tokens=5" %a in (d:\aa.txt) do @echo %a
会显⽰:
<
<
批处理文件怎么做<
free
本意想把⽂件⾥列出的⽂件显⽰出来(当然也可以换成对⽂件进⾏其他命令操作)
通过skip=5 忽略掉前5⾏,默认以空格分隔后tokens=5取每⾏第五段字符就顺利地把⽂件名赋给变量%a,美中不⾜最后⼀⾏取了个不是⽂件名的(当然可⽤其他⽅法处理这个多余的只是for/f中没提供忽略最后⼏⾏的格式),⽽倒数第⼆⾏则⽆第五段。
显然例中aa.txt⾥的内容是某次执⾏dir命令后的内容。它可⽤类似命令:
dir > d:\aa.txt来建⽴
题外话,如果在dir中加⼊合适的参数/b,就可以回避多余的部分,还可加⼊/ad只显⽰⽬录,加⼊/a-d只显⽰⽂件等
那么,我们完全可以直接书写命令放⼊in后的(‘命令’-集)中
for /f "skip=5 tokens=5 " %a in ('dir') do @echo %a
效果⼀样。
注:命令集需⽤单引号括起来以表⽰不是⽂件集,如⽤双引号括起来则表⽰是字符串集,本例是为了说明for命令的⽤法,真正有这种⽤途也愿意⽤前⾯“题外话”的⽅法。如果你在执⾏本例后什么也没显⽰,你需要先⽤集⾥的命令先执⾏⼀次,看它显⽰的格式,也许需要把tokens=5 改成tokens=4 或许还应当给dir加上参数 /a-d以回避显⽰出⽬录。
如果集⾥是由多个⽂件组成,那么处理完⼀个⽂件后⼜处理完⼜去处理另⼀个⽂件,每个⽂件⾏数不同循环次数(do命令的次数)也将因此不同。
如果集⾥是由命令产⽣的系统,那么你必须⾸先熟悉该命令执⾏后会产⽣怎样效果的字符系统,才能正确安排后⾯的do命令
画龙点睛:⽆论in后的集是哪种形式,for/f 都最终分解为字符串,按需要是否“忽略⼏⾏”(skip=)、“⽤什么⼑来切分”(delims=)、“最多只需取哪⼏段”(tokens=)将集⾥形成的字符串,逐⾏地分段赋给%或%%后的变量及可能顺延扩展出的变量,以执⾏do后的命令,每⼀⾏即为⼀轮循环。这⾥没完整说明全部参数,请在命令⾏⽤for/?查看。(下⾯的斜体字是复制的帮助⾥的内容)
例如:
对于带有空格的⽂件名,您需要⽤双引号将⽂件名括起来。为了⽤这种⽅式来使⽤双引号,您还需要使⽤ usebackq 选项,否则,双引号会被理解成是⽤作定义某个要分析的字符串的。——换句话说,带有usebackq(放在for /f 之后的引号⾥)参数时 in ()⾥⽤双引号表⽰的仍是⽂件名。
还有⼀个选项eol= :前⾯所说skip=是表⽰忽略开始的⼏⾏,其实默认状况还忽略所有分号“ ; ”开始的⾏,如果你想不忽略分号开始的⾏,或者想忽略⾃⼰指定⼀字符开始的⾏就可以在for /f 之后那引号参数⾥使⽤eol=你⾃⼰定义的字符,但它不像delims=的那样可定义多个,只允许定义⼀个。
另⼀花样:可以⽤ %~ 操作符将⽂件名分离成⽂件名、扩展名、盘符等独⽴部分 ,请看for/?中的解释(其中⽰例的变量为%I):项⽬Value
~I删除任何引号("),扩充 %I
%~fI将 %I 扩充到⼀个完全合格的路径名
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论