批处理——for

摘自:http://bbs.bathome.net/thread-2189-1-1.html

批处理

1 基础

1.1 切换工作路径

将工作路径切换为.bat文件所在的位置

cd /d %~dp0

1.2 显示工作路径下的所有文件

/b 显示文件夹或文件的名字
/s 显示指定目录和所有子目录中的文件。
@echo off
dir /s /b *.* > C:\Users\DELL\Desktop\test.txt

当然也可以使用for循环:

@echo off
for %%i in (*.*) do echo "%%i"
pause

1.3 提取文件里的内容

下述代码会提取test.txt里的内容

@echo off
for /f %%i in (test.txt) do echo %%i
pause

for /f是以行为单位进行处理的,即每次for循环处理一行。

这段代码,主要是让你树立这样一种观念:读取文本文件的内容,请使用 for/f 语句!

下述命令是每输出一行就暂停!!!!!!!!!

@echo off
cd /d  %~dp0
for /f %%i in (test.txt) do echo %%i&pause
pause

1.4 修改编码

使用chcp 来修改编码

@echo off
chcp  65001
cd /d  %~dp0
for /f "delims=, " %%i in (test.txt) do echo %%i
pause
    1258 越南语
    1257 波罗的语
    1256 阿拉伯语
    1255 希伯来语
    1254 土耳其语
    1253 希腊语
    1252 拉丁 1 字符 (ANSI)
    1251 西里尔语
    1250 中欧语言
    950 繁体中文
    949 朝鲜语
    936 简体中文(默认)
    932 日语
    874 泰国语
    850 多语种 (MS-DOS Latin1)
    437 MS-DOS 美国英语
    65001 UTF-8

但是有一个问题需要注意,被处理的对象65001编码,这个.bat或才.cmd文件的编码应与之相同,否则会出现意想不到的问题

1.5 分隔提取

@echo of
for /f "delims=., " %%i in (test.txt) do echo %%i
pause

注意delims=后面跟着的是一个符号列表,也就是说可以不只一个符号。以上述例子为例,第一个点号或第一个逗号之前的内容都被提取出来了。

上述命令只提取第一个,如果需要自定义提取,则用token

@echo off
chcp 65001
cd /d  %~dp0for /f "delims=, tokens=2,4" %%i in (test.txt) do echo %%i %%j
pause

上述命令有token=2,4表示提取第2个、第4个(从1开始),注意因为提取了两个,所以还要有%j

当然token可以连续写比如:

@echo off
chcp 65001
cd /d  %~dp0for /f "delims=, tokens=3-5,6,7,9" %%i in (test.txt) do echo %%i %%j
pause

token=后面的东西可以怎么方便怎么写。

下面给出带星号的表示:

@echo off
for /f "delims=, tokens=1,*" %%i in (test.txt) do echo %%i %%j
pause

结果,第一个逗号不见了,取代它的是一个空格符号,其余部分保持不变。
其中奥妙就在这个星号上面。tokens=后面所接的星号具备这样的功能:字符串从左往右被切分成紧跟在之前的数值所表示的节数之后,字符串的其余部分保持不变,整体被所表示的一个变量接收。**

*上述代码的具体情况就是[txt2] 的内容被切分,切分符号为逗号,当切分完第一节之后,切分动作不再继续下去,因为 tokens=1, 中,星号前面紧跟的是数字 **1;第一节字符串被切分完之后,其余部分字符串不做任何切分,整体作为第二节字符串,这样, [txt2]就被切分成了两节,分别被变量%%i 和变量%%j 接收。

1.6 跳过

@echo off
for /f "skip=2" %%i in (test.txt) do echo %%i
pause

这段代码将跳过头两行内容,从第 3 行起显示 test.txt 中的信息

1.7 忽略分号

for /f 语句是默认忽略以分号打头的行内容的,正如它默认以空格键或跳格键作为字符串的切分字符一样。

所以在处理下述三行中,前两行会被跳过不显示任何东西

​ ;论坛的目标是:不求最大,但求最好,做最实用的批处理论坛。
​ ;论坛地址: bbs.bathome.cn。
​ 这里是:新手晋级的福地,高手论剑的天堂。

若要改为其他字符,则可以按如下操作:

@echo off
for /f "eol=;" %%i in (test.txt) do echo %%i
pause

eol= 的准确含义是:忽略以指定字符打头的行。

1.8 usebackq

usebackq 是一个增强型参数,当使用了这个参数之后,原来的 for语句中第一个括号内的写法要做如下变动:如果第一个括号里的对象是一条命令语句的话,原来的单引号’要改为后引号`;如果第一个括号里的对象是字符串的话,原来的双引号"要改为单引号’;如果第一个括号里的对象是文件名的话,要用双引号"括起来。w例子如下:

@echo off
for /f "usebackq" %%i in ("test 1.txt") do echo %%i
pause

1.9 总结

1、当你希望读取文本文件中的内容的话,第一个括号中不用任何符号包裹,应该使用的是第 1 条语句;例如:你想显示 test.txt 中的内容,那么,就使用 for/f %%i in (test.txt) do echo %%i;
2、当你读取的是命令语句执行结果中的内容的话,第一个括号中的命令语句必须使用单引号包裹,应该使用的是第 2 条语句;例如:你想显示当前目录下批处理For 语句从入门到精通(bbs.bathome.net)文件名中含有 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、 for /f %%i in (文件名) do („„)
2、 for /f %%i in (‘命令语句’) do („„)
3、 for /f %%i in (“字符串”) do („„)
4、 for /f “usebackq” %%i in (“文件名”) do („„)
5、 for /f “usebackq” %%i in (命令语句) do („„)
6、 for /f “usebackq” %%i in (‘字符串’) do („„)

2进阶

2.1 延时

setlocal enabledelayedexpansion

类似verilog里的阻塞赋值,如果不设置就相当于非阻塞赋值了。举例如下:

@echo off
set num=0
setlocal enabledelayedexpansion
for /f %%i in ('dir /a-d /b *.exe') do (
set /a num+=1
echo num 当前的值是 !num!
)
echo 当前目录下共有 %num% 个 exe 文件
dir /a-d /b *.txt|findstr "test">nul&&(
echo 存在含有 test 字符串的文本本件)||echo 不存在含有 test 字符串的文本文件
if exist test.ini (
echo 存在 test.ini 文件) 
else 不存在 test.ini 文件
pause

由此可见,如果使用 setlocal enabledelayedexpansion 语句来延迟变量,就要把原本使用百分号对闭合的变量引用改为使用感叹号对来闭合;如果使用 call
语句,就要在原来命令的前部加上 call 命令,并把变量引用的单层百分号对改为双层。 其中,因为 call 语句使用的是双层百分号对,容易使人犯迷糊,所以用得较少,常用的是使用 setlocal enabledelayedexpansion 语句(set 是设置的意思, local 是本地的意思, enable 是能够的意思, delayed 是延迟的意思, expansion是扩展的意思,合起来,就是:让变量成为局部变量,并延迟它的扩展行为)。

1、怎样使用变量延迟?
方法有两种:
① 使用 setlocal enabledelayedexpansion 语句:在获取变化的变量值语句批处理 For 语句从入门到精通(bbs.bathome.net)之前使用 setlocal enabledelayedexpansion,并把原本使用百分号对闭合的变量引用改为使用感叹号对来闭合;
② 使用 call 语句:在原来命令的前部加上 call 命令,并把变量引用的单层百分号对改为双层。

2.2 for /r

此命令用于递归地遍历文件夹

for /r 目录 %%i in (元素集合) do 命令语句集合

举例如下:

@echo off
for /r d:\test %%i in (.) do echo %%i
pause

但是我们知道 1.2节里指出dir也可列出文件夹,那么两者有什么区别呢?

1、 for /r 列举出来的路径最后都带有斜杠和点号,而 dir 语句则没有,会对获取到的路径进行进一步加工产生影响;
2、 for /r 不能列举带隐藏属性的目录,而 dir 语句则可以通过指定 /a 后面紧跟的参数来获取带指定属性的目录,更加灵活;
3、若要对获取到的路径进行进一步处理,则需要把 dir 语句放入 for /f 语句中进行分析,写成 for /f %%i in (‘dir /ad /b /s’) do „„ 的形式;由于 for /r 语句是边列举路径边进行处理,所以,在处理大量路径的时候,前期不会感到有停顿,而 for /f 语句则需要等到 dir /ad /b /s 语句把所有路径都列举完之后,再读入内存进行处理,所以,在处理大量路径的时候,前期会感到有明显的停顿

1、 for /r:
1)优点:
① 只通过 1 条语句就可以同时实现获取目录路径和处理目录路径的操作;
② 遍历文件夹的时候,是边列举边处理的,获取到一条路径就处理一条路径,内存占用小,处理大量路径的时候不会产生停顿感;
2)缺点:
① 不能获取到带隐藏属性的目录,会产生遗漏;
② 不能获取带指定属性的目录
2、 dir /ad /s:
1)优点:
① 能一次性获取带任意属性的目录,不会产生遗漏;
② 能通过指定不同的参数获取带任意属性的目录,更具灵活性。
2)缺点:
① dir /ad /s 语句仅能获取到目录路径,若要实现进一步的处理,还需要嵌入 for /f 语句中才能实现,写法不够简洁;
② 嵌入 for /f 语句之后,需要写成 for /f “delims=” %%i in (‘dir /ad /b /s’)do „„ 的格式,受 for /f 语句运行机制的制约,需要先列举完所有的路径放入内存之后,才能对每一条路径进行进一步的处理,处理大量路径时,内存占用量偏大,并且在前期会产生明显的停顿感,用户体验度不够好;

综上所述,还是尽量使用dir命令吧

2.3 for /d

它仅能匹配当前目录下的第一级文件夹,或是指定位置上的文件夹,而不能匹配更深层次的子文件夹。例如: for /d %%i in (d:\test*) do echo %%i 这样的语句 ,会匹配到形如:d:\test、 d:\test1、 d:\test2 之类的文件夹,若不存在这样的路径,将不会有任何回显

2.4 for /l

其中l是loop的意思,意为循环

for /l %%i in (1,2,10) do echo bathome

在以上的代码中,初始值是 1,步长为 2,终止值为 10,表明计数从 1 开始,每隔 2 个数计算一次,直至最接近 10 的那个整数,罗列出来,就是 1,3,5,7,9,再下一个就是 11,超过 10 了,不再计算在内,所以, do 后的语句只执行 5 次,将连续显示 5 个 bathome。

实际上, x, y 和 z 的值可正可负,甚至为 0,限制非常宽松:
1、步长 y 的值不能为 0;
2、当步长 y 的值为正整数时,终止值 z 不能小于初始值 x;
3、当步长 y 的值为负整数的时候,终止值 z 不能大于初始值 x。
换而言之,必须保证 in 和 do 之间能取到一个有效的数组序列。

for /l %%i in (-1,2,5) do echo bathome
for /l %%i in (5,-2,-1) do echo bathome  

以上两条代码的功能完全一样,都将显示 4 次 bathome,区别就在于是正序计数、逆序计数而已。

当循环次数确定的时候,首选 for /l 语句,也可使用 goto语句但不推荐;当循环次数不确定的时候,用 goto 语句将是唯一的选择,因为,这个时候需要用 if 之类的条件语句来判断何时结束 goto 跳转。

你可能感兴趣的:(工具)