[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

批处理FOR的命令行分析机制

原文地址:http://www.cn-dos.net/forum/viewthread.php?tid=21432
作者:willsort
发表日期:2006-6-22

To All:

      FOR的命令行分析机制是很复杂,有很多可以讨论的细节,这里首先讨论的是容易惹人疑窦的遍历集合(也就是in后do前括号中的部分)的分析机制。

      在此之前,首先提出一个应用上的实际问题[1]。严格的说,这不能算是FOR的一个BUG,而是对旧有语法特性的沿袭不当。

      关于FOR的旧有语法特性,[2] 中曾有讨论,现略作整理和补充:

      1、IN语句后()中内容被称为FOR的遍历集合,其中可以包含多个元素,每个元素之间以空格、分号、等号等参数分隔符分隔。FOR将按以下过程一一处理所有的元素。

      2、如果元素中含有文件名通配符(星号或问号),则FOR将此元素理解为文件名,它将在当前路径或者元素中所指定的路径下寻找可以对应的文件。如果找到,则用其文件名逐个替换并执行DO后的语句;如果未找到,则不执行DO后的语句,也不作任何提示。

      3、如果元素中不含有文件名通配符,则FOR则将其理解为普通意义的字符串,替换并执行DO后的语句。

      4、在文件名的替换过程中,如果元素中指定了路径,那么其替换后的FOR变量中也将包含同样的路径,反之亦然。

      5、在MSDOS6及其以下版本中,不支持长文件名,因此也不支持引号包含的文件名,所以在遍历元素中同时使用引号和通配符时,将没有任何执行结果。

      简而言之,如果有通配符则进行文件名的替换,否则进行字符串的替换。

      在后来的MSDOS7.10/COMMAND@Win9x/CMD@WinNT中,这个特性继续保留,只是在此基础上增加了对含引号文件名的识别和分析。

      至于在FOR/R和FOR/D仍然为何仍然沿袭这个特性,这确实是个值得讨论的问题,因为绝大多数情况下,我们使用FOR/R或FOR/D的目的,都是要进行文件或目录名的替换,而非普通文本的替换。

      但显然,FOR命令的设计思路与我们是有分歧的,且翻阅一下FOR的命令行帮助信息[3]。此时,我们可以揣测一下这个设计思路是什么:FOR/D只是将文件名匹配切换为目录名匹配,FOR/R只是将指定目录的匹配切换为指定目录树的匹配,这均不会也不该影响文件名和字符串的匹配选择。这样的设计,使程序的改动尽可能的小,至少遍历集合分析的代码不需要太大的改动。

      然而,会有多少人知道并理解这个特性呢?

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


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

[2] 运行XMSDSK 后,在他的虚拟盘目录下,循环FOR就不支持*统配符了?
http://www.cn-dos.net/forum/viewthread.php?tid=15744

[3] FOR /? in CMD@WinXP

FOR /D %variable IN (set) DO command [command-parameters]

    如果集中包含通配符,则指定与目录名匹配,而不与文件
    名匹配。

FOR /R [[drive:]path] %variable IN (set) DO command [command-parameters]

    检查以 [drive:]path 为根的目录树,指向每个目录中的
    FOR 语句。如果在 /R 后没有指定目录,则使用当前
    目录。如果集仅为一个单点(.)字符,则枚举该目录树。
尺有所短寸有所长,学好批处理没商量;
考虑问题复杂化,解决问题简洁化。

心在天山,身老沧州。

for /f %%i in (文件名) do (……)
记得好像有这样的句型.
"简而言之,如果有通配符则进行文件名的替换,否则进行字符串的替换。"这句话我记住了,在for /r或者for /d的时候,不行的话就加个通配试试了.
虽然总结的不错,但我还是不太明白

TOP

返回列表