Board logo

标题: [转] 批处理for /d 、for /r 教程 [打印本页]

作者: vsbat    时间: 2009-11-13 13:35     标题: [转] 批处理for /d 、for /r 教程

众所周知 for /f for /l 功能强大----但好像很少有人用for/r for/d --近日见此二参数问题较多
特从网络转此经典教程,供大家学习---
[由于此文章实在是转载频繁,无法获知作者,所以只注明:转自网络]




FOR %%variable IN (set) DO command [command-parameters]
%%variable 指定一个单一字母可替换的参数。
(set)      指定一个或一组文件。可以使用通配符。
command    指定对每个文件执行的命令。
command-parameters
             为特定命令指定参数或命令行开关。

现在开始讲每个参数的意思
/d
仅为目录
如果 Set (也就是我上面写的 "相关文件或命令") 包含通配符(* 和 ?),将对与 Set 相匹配的每个目
录(而不是指定目录中的文件组)执行指定的 Command。
系统帮助的格式:FOR /D %%variable IN (set) DO command
他主要用于目录搜索,不会搜索文件,看这样的例子
@echo off
for /d %%i in (*) do @echo %%i
pause
把他保存放在C盘根目录执行,就会把C盘目录下的全部目录名字打印出来,而文件名字一个也不显示!
在来一个,比如我们要把当前路径下文件夹的名字只有1-3个字母的打出来
@echo off
for /d %%i in (???) do @echo %%i
pause
这样的话如果你当前目录下有目录名字只有1-3个字母的,就会显示出来,没有就不显示了

思考题目:
@echo off
for /d %%i in (window?) do @echo %%i
pause
保存到C盘下执行,会显示什么呢?自己看吧!
/D参数只能显示当前目录下的目录名字,这个大家要注意!
/R
递归
进入根目录树 [Drive:]Path,在树的每个目录中执行 for 语句。如果在 /R 后没有指定目录,则认为是
当前目录。如果 Set 只是一个句点 (.),则只枚举目录树。
系统帮助的格式:FOR /R [[drive:]path] %%variable IN (set) DO command
上面我们知道,/D只能显示当前路径下的目录名字,那么现在这个/R也是和目录有关,他能干嘛呢?放心他比
/D强大多了!
他可以把当前或者你指定路径下的文件名字全部读取,注意是文件名字,有什么用看例子!
@echo off
for /r c:\ %%i in (*.exe) do @echo %%i
pause
咋们把这个BAT保存到D盘随便哪里然后执行,我会就会看到,他把C盘根目录,和每个目录的子目录下面全部
的EXE文件都列出来了,这里的c:\就是目录了。
再来一个
@echo off
for /r %%i in (*.exe) do @echo %%i
pause
参数不一样了,这个命令前面没加那个C:\也就是搜索路径,这样他就会以当前目录为搜索路径,比如你这
个BAT你把他防灾d:\test目录下执行,那么他就会把D:\test目录和他下面的子目录的全部EXE文件列出
来!!!
******************************************************************************************************************************************
自己也是才知道,原来 for /r  存在bug
为方便学习----丰富教程
引用 cn-dos  willsort 的分析如下:

[1] FOR/R syntax bug
http://groups.google.com/group/a ... d/84b80fadc616f74a/


  Quote:
E:\>dir/s/b
File Not Found

E:\>md test

E:\>echo test>test\x.txt

E:\>for /r %f in (x.txt) do @echo %f
E:\x.txt
E:\test\x.txt

E:\>for /r %f in (x.txt*) do @echo %f
E:\test\x.txt

********************************************************************************************************************************
er--------------------
这就是在不断犯错中成长------十分感谢 zqz 版主的 解释----
现把他的解释 和 其中的链接放在 一楼 方便大家学习------
zqz 版主 10 楼:
你所转的willsort的帖子内容其实并不是Bug,而是for的一种运行机制。
http://www.bathome.net/viewthread.php?tid=4804&page=1#pid30833 引用:
2、for、for /r 其实并不枚举文件,它们的循环对象就是字符串,除了一个例外:循环集含有通配符*、?。
for %%a in (*) do echo %%a
这个时候你没办法将*、?当作普通字符,加^转义也不行。
for /r 的循环方式是对每个目录执行一次,在循环集里的字符串前面加上目录名(构成%%a)。
类似于for /l 的循环方式是对每个数执行一次。

8楼说的Bug是,如果循环过程中有文件名变动或新文件生成,有时会导致某些文件循环两次(暂未发现文件遍历不到的情况),也就是说循环过程被扰乱了。但这个bug只是偶尔出现甚至不会出现,难以追踪。

zqz  11 楼:
linux中,命令中的普通通配符是由shell完成扩展的。
例如 ls *.txt
如果当前目录有1.txt 2.txt两个文件,则*.txt被shell自动扩展为实际文件名,因此ls实际执行的命令是
ls 1.txt 2.txt
类似地,echo *.txt 将显示1.txt 2.txt而不是字面上的*.txt
所以有时经常需要对通配符转义或用引号括起来防止shell的自动扩展。

cmd中for的运行机制与此类似(注意只是类似而不等同)。



[ 本帖最后由 vsbat 于 2009-11-20 21:19 编辑 ]
作者: drefong    时间: 2009-11-13 13:49

顶,找了很久了饿
作者: nerfg002    时间: 2009-11-13 15:23

支持 一下,FOR很强大
作者: zqz0012005    时间: 2009-11-13 19:01

verybat 论坛 伤脑筋 出的系列教程之一:
第二节(for命令详解)
http://bbs.verybat.org/viewthread.php?tid=220

verybat 以前还是挺不错的,出过不少精华文章。鄙人也曾经在那里学习探讨过,也发表了一些粗浅的文章(本人并没有完全放弃verybat,一直期待管理员重新带领verybat走上正轨)。出于某些原因,那里的文章(本人原创或其他人的)我不想在此转载,给出链接足以。
作者: vsbat    时间: 2009-11-13 19:12

同意 zqz 版主的意见----
vbt  有不少好教程---比如 英雄 的 一系列---
建议大家去取取经===

[ 本帖最后由 vsbat 于 2009-11-17 13:58 编辑 ]
作者: pumahxh    时间: 2009-11-15 16:46

for /d的功能,看起来对应dir /ad-s
for /r的功能,对应dir /s /ad-s
作者: luzhanhong    时间: 2009-11-19 11:29

学习了啦.........
作者: zqz0012005    时间: 2009-11-20 00:16

以前讨论过,
文件有变动时,最好不要用for /d、for /r,而改为用for /f 解析dir的输出。
因为前种方式有bug,而且难以追踪,有时出现有时不会出现,不同的电脑环境也有不同结果。
作者: batman    时间: 2009-11-20 00:26     标题: 回复 8楼 的帖子

zqz所言即是,建议大家多使用for /f,少用for /d for /r,因为一方面前者存在bug,另一方面for /f独有eol skip tokens delims参数功能比前者不知强了多少倍。
作者: zqz0012005    时间: 2009-11-20 21:02     标题: 回复 1楼 的帖子

你所转的willsort的帖子内容其实并不是Bug,而是for的一种运行机制。
http://www.bathome.net/viewthrea ... amp;page=1#pid30833
2、for、for /r 其实并不枚举文件,它们的循环对象就是字符串,除了一个例外:循环集含有通配符*、?。
for %%a in (*) do echo %%a
这个时候你没办法将*、?当作普通字符,加^转义也不行。
for /r 的循环方式是对每个目录执行一次,在循环集里的字符串前面加上目录名(构成%%a)。
类似于for /l 的循环方式是对每个数执行一次。


8楼说的Bug是,如果循环过程中有文件名变动或新文件生成,有时会导致某些文件循环两次(暂未发现文件遍历不到的情况),也就是说循环过程被扰乱了。但这个bug只是偶尔出现甚至不会出现,难以追踪。
作者: vsbat    时间: 2009-11-20 21:13     标题: 回复 10楼 的帖子

ganxie 楼上--------------
已在楼顶说明-----方便大家
---------------
作者: zqz0012005    时间: 2009-11-20 21:16

linux中,命令中的普通通配符是由shell完成扩展的。
例如 ls *.txt
如果当前目录有1.txt 2.txt两个文件,则*.txt被shell自动扩展为实际文件名,因此ls实际执行的命令是
ls 1.txt 2.txt
类似地,echo *.txt 将显示1.txt 2.txt而不是字面上的*.txt
所以有时经常需要对通配符转义或用引号括起来防止shell的自动扩展。

cmd中for的运行机制与此类似(注意只是类似而不等同)。




欢迎光临 批处理之家 (http://bbs.bathome.net/) Powered by Discuz! 7.2