http://blog.neu.edu.cn/elm/archives/104

以前常觉得DOS的命令行功能太弱,无法象UNIX一样可以用命令行完成非常复杂的操作。实际上,当MS从WIN2K开始将命令行增强后,已经借鉴 了相当多UNIX的优点,虽然还无法做到象UNIX那么灵活,但已可完成绝大多数的任务,比如用&&和||连接两个(或更多)命令,由前 一个的返回值来决定下一个是否执行,等等。而在这些增强中,最明显的,就是FOR命令。

举个例子,用适当的参数,可用FOR命令将 date /t 的输出 从 “Sat 07/13/2002″ 变成你想要的格式,比如, “2002-07-13″:

c:>for /f “tokens=2,3,4 delims=/ ” %a in (‘date /t’) do @echo %c-%a-%b      2002-07-13

该例将在(3)中详细说明。

0. 基本应用

简单说,FOR是个循环,可以用你指定的循环范围生成一系列命令。最简单的例子,就是人工指定循环范围,然后对每个值执行指定的命令。例如,想快速报告每个硬盘分区的剩余空间:

for %a in (c: d: e: f:) do @dir %a|find “可用字节”

将输出:

8 Dir(s)       1,361,334,272 bytes free
15 Dir(s)       8,505,581,568 bytes free
12 Dir(s)      12,975,149,056 bytes free
7 Dir(s)      11,658,854,400 bytes free

用它可以使一些不支持通配符的命令对一系列文件进行操作。在WIN9X中,TYPE命令(显示文件内容)是不支持*.txt这种格式的(WIN2K开始TYPE已支持通配)。遇到类似情况就可以用FOR:

for %a in (*.txt) do type %a

这些还不是FOR最强大的功能。我认为它最强大的功能,表现在以下这些高级应用:

1. 可以用 /r 参数遍历整个目录树
2. 可以用 /f 参数将文本文件内容作为循环范围
3. 可以用 /f 参数将某一命令执行结果作为循环范围
4. 可以用 %~ 操作符将文件名分离成文件名、扩展名、盘符等独立部分
现分别举例说明如下:

1. 用 /r 遍历目录树

当用 *.* 或 *.txt 等文件名通配符作为 for /r 的循环范围时,可以对当前目录下所有文件(包括子目录里面的文件)进行操作。举个例子,你想在当前目录的所有txt文件(包括子目录)内容中查 找”bluebear”字样,但由于find本身不能遍历子目录,所以我们用for:

for /r . %a in (*.txt) do @find “bluebear” %a

find 前面的 @ 只是让输出结果不包括 find 命令本身。这是DOS很早就有的功能。和FOR无关。

当用 . 作为循环范围时,for 只将子目录的结构(目录名)作为循环范围,而不包括里面的文件。有点象 TREE 命令,不过侧重点不同。TREE 的重点是用很漂亮易读的格式输出,而FOR的输出适合一些自动任务,例如,我们都知道用CVS管理的项目中,每个子目录下都会有一个CVS目录,有时在软 件发行时我们想把这些CVS目录全部去掉:

for /r . %a in (.) do @if exist %aCVS rd /s /q %aCVS

先用 if exist 判断一下,是因为 for 只是机械的对每个目录进行列举,如果有些目录下面没有CVS也会被执行到。用 if exist 判断一下比较安全。

这种删除命令威力太大,请小心使用。最好是在真正执行以上的删除命令前,将 rd /s /q 换成 @echo 先列出要删出的目录,确认无误后再换回rd /s /q:

for /r . %a in (.) do @if exist %aCVS @echo %aCVS

可能目录中会多出一层 “.”,比如 c:projrelease.CVS ,但不会影响命令的执行效果。

2. 将某一文件内容或命令执行结果作为循环范围:

假如你有一个文件 todel.txt,里面是所有要删除的文件列表,现在你想将里面列出的每个文件都删掉。假设这个文件是每个文件名占一行,象这样:

c:tempa1.txt      c:tempa2.txt      c:tempsubdirb3.txt      c:tempsubdirb4.txt

那么可以用FOR来完成:

for /f %a in (todel.txt) do del %a

这个命令还可以更强大。比如你的 todel.txt 并不是象上面例子那么干净,而是由DIR直接生成,有一些没用的信息,比如这样:

Volume in drive D is DATA
Volume Serial Number is C47C-9908

Directory of D:tmp

09/26/2001      12:50 PM                18,426 alg0925.txt
12/02/2001      04:29 AM                   795 bsample.txt
04/11/2002      04:18 AM                 2,043 invitation.txt
4 File(s)             25,651 bytes
0 Dir(s)       4,060,700,672 bytes free

for 仍然可以解出其中的文件名并进行操作:

for /f “skip=5 tokens=5″ %a in (todel.txt) do @if exist %a DEL %a

当然,上面这个命令是在进行删除,如果你只是想看看哪些文件将被操作,把DEL换成echo:

for /f “skip=5 tokens=5″ %a in (todel.txt) do @if exist %a echo %a

你将看到:

alg0925.txt
bsample.txt
invitation.txt

skip=5表示跳过前5行(就是DIR输出的头部信息),tokens=5表示将每行的第5列作为循环值放入%a,正好是文件名。在这里我加了一 个文件存在判断,是因为最后一行的”free”刚好也是第5列,目前还想不出好的办法来滤掉最后两行,所以检查一下可保万无一失。

3. 可以用 /f 参数将某一命令执行结果作为循环范围

非常有用的功能。比如,我们想知道目前的环境变量有哪些名字(我们只要名字,不要值)。可是SET命令的输出是“名字=值”的格式,现在可以用FOR来只取得名字部分:

FOR /F “delims==” %i IN (‘set’) DO @echo %i

将看到:

ALLUSERSPROFILE
APPDATA
CLASSPATH
CommonProgramFiles
COMPUTERNAME
ComSpec
dircmd
HOMEDRIVE      ……

这里是将set命令执行的结果拿来作为循环范围。delims==表示用=作为分隔符,由于FOR /F默认是用每行第一个TOKEN,所以可以分离出变量名。如果是想仅列出值:

FOR /F “delims== tokens=2″ %i IN (‘set’) DO @echo %i

tokens=2和前例相同,表示将第二列(由=作为分隔符)作为循环值。

再来个更有用的例子:

我们知道 date /t (/t表示不要询问用户输入)的输出是象这样的:

Sat 07/13/2002

现在我想分离出日期部分,也就是13:

for /f “tokens=3 delims=/ ” %a in (‘date /t’) do @echo %a

实际上把 tokens后面换成1,2,3或4,你将分别得到Sat, 07, 13和2002。注意delims=/后面还有个空格,表示/和空格都是分隔符。由于这个空格delims必须是/f选项的最后一项。

再灵活一点,象本文开头提到的,将日期用2002-07-13的格式输出:

for /f “tokens=2,3,4 delims=/ ” %a in (‘date /t’) do @echo %c-%a-%b

当tokens后跟多个值时,将分别映射到%a, %b, %c等。实际上跟你指定的变量有关,如果你指定的是 %i, 它们就会用%i, %j, %k等。

灵活应用这一点,几乎没有做不了的事。

4. 可以用 %~ 操作符将文件名分离成文件名、扩展名、盘符等独立部分

这个比较简单,就是说将循环变量的值自动分离成只要文件名,只要扩展名,或只要盘符等等。

例:要将 c:mp3下所有mp3的歌名列出,如果用一般的 dir /b/s 或 for /r ,将会是这样:

g:mp3Archived5-18-01-A游鸿明-下沙游鸿明-01 下沙.mp3
g:mp3Archived5-18-01-A游鸿明-下沙游鸿明-02 21个人.mp3
……
g:mp3Archived5-18-01-A王菲-寓言王菲-阿修罗.mp3
g:mp3Archived5-18-01-A王菲-寓言王菲-彼岸花.mp3
g:mp3Archived5-18-01-A王菲-寓言王菲-不爱我的我不爱.mp3
……

如果我只要歌名(不要路径和”.mp3″):

游鸿明-01 下沙
游鸿明-02 21个人
……
王菲-阿修罗
王菲-彼岸花
王菲-不爱我的我不爱
……

那么可以用FOR命令:

for /r g:mp3 %a in (*.mp3) do @echo %~na

凡是 %~ 开头的操作符,都是文件名的分离操作。具体请看 for /? 帮助。

本文举的例子有些可能没有实际用处,或可用其它办法完成。仅用于体现FOR可以不借助其它工具,仅用DOS命令组合,就可完成相当灵活的任务。

具体请看 for /? 帮助

For命令具体解释

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

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

在批处理文件中使用 FOR 命令时,指定变量请使用 %%variable 而不要用 %variable。变量名称是区分大小写的,所以 %i 不同于 %I.

如果命令扩展名被启用,下列额外的 FOR 命令格式会受到支持:

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 /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)。

FOR /F ["options"] %variable IN (file-set) DO command [command-parameters]
FOR /F ["options"] %variable IN (“string”) DO command [command-parameters]
FOR /F ["options"] %variable IN (‘command’) DO command [command-parameters]

或者,如果有 usebackq 选项:

FOR /F ["options"] %variable IN (file-set) DO command [command-parameters]
FOR /F ["options"] %variable IN (“string”) DO command [command-parameters]
FOR /F ["options"] %variable IN (‘command’) DO command [command-parameters]

filenameset 为一个或多个文件名。继续到 filenameset 中的下一个文件之前,每份文件都已被打开、读取并经过处理。处理包括读取文件,将其分成一行行的文字,然后将每行解析成零或更多的符号。然后用已找到的符 号字符串变量值调用 For 循环。以默认方式,/F 通过每个文件的每一行中分开的第一个空白符号。跳过空白行。您可通过指定可选 “options” 参数替代默认解析操作。这个带引号的字符串包括一个或多个指定不同解析选项的关键字。这些关键字为:

eol=c – 指一个行注释字符的结尾(就一个)
skip=n – 指在文件开始时忽略的行数。
delims=xxx – 指分隔符集。这个替换了空格和跳格键的
默认分隔符集。
tokens=x,y,m-n – 指每行的哪一个符号被传递到每个迭代
的 for 本身。这会导致额外变量名称的分配。m-n
格式为一个范围。通过 nth 符号指定 mth。如果
符号字符串中的最后一个字符星号,
那么额外的变量将在最后一个符号解析之后
分配并接受行的保留文本。
usebackq – 指定新语法已在下类情况中使用:
在作为命令执行一个后引号的字符串并且一个单
引号字符为文字字符串命令并允许在 filenameset
中使用双引号扩起文件名称。

某些范例可能有助:

FOR /F “eol=; tokens=2,3* delims=, ” %i in (myfile.txt) do @echo %i %j %k

会 分析 myfile.txt 中的每一行,忽略以分号打头的那些行,将每行中的第二个和第三个符号传递给 for 程序体;用逗号和/或空格定界符号。请注意,这个 for 程序体的语句引用 %i 来取得第二个符号,引用 %j 来取得第三个符号,引用 %k 来取得第三个符号后的所有剩余符号。对于带有空格的文件名,您需要用双引号将文件名括起来。为了用这种方式来使用双引号,您还需要使用 usebackq 选项,否则,双引号会被理解成是用作定义某个要分析的字符串的。

%i 专门在 for 语句中得到说明,%j 和 %k 是通过 tokens= 选项专门得到说明的。您可以通过 tokens= 一行指定最多 26 个符号,只要不试图说明一个高于字母 ‘z’ 或 ‘Z’ 的变量。请记住,FOR 变量是单一字母、分大小写和全局的;而且,同时不能有 52 个以上都在使用中。

您还可以在相邻字符串上使用 FOR /F 分析逻辑;方法是,用单引号将括号之间的 filenameset 括起来。这样,该字符串会被当作一个文件中的一个单一输入行。

最后,您可以用 FOR /F 命令来分析命令的输出。方法是,将括号之间的 filenameset 变成一个反括字符串。该字符串会被当作命令行,传递到一个子 CMD.EXE,其输出会被抓进内存,并被当作文件分析。因此,以下例子:

FOR /F “usebackq delims==” %i IN (`set`) DO @echo %i

会枚举当前环境中的环境变量名称。

另外,FOR 变量参照的替换已被增强。您现在可以使用下列选项语法:

~I – 删除任何引号(“),扩充 %I
%~fI – 将 %I 扩充到一个完全合格的路径名
%~dI – 仅将 %I 扩充到一个驱动器号
%~pI – 仅将 %I 扩充到一个路径
%~nI – 仅将 %I 扩充到一个文件名
%~xI – 仅将 %I 扩充到一个文件扩展名
%~sI – 扩充的路径只含有短名
%~aI – 将 %I 扩充到文件的文件属性
%~tI – 将 %I 扩充到文件的日期/时间
%~zI – 将 %I 扩充到文件的大小
%~$PATH:I – 查找列在路径环境变量的目录,并将 %I 扩充
到找到的第一个完全合格的名称。如果环境变量名
未被定义,或者没有找到文件,此组合键会扩充到
空字符串

可以组合修饰符来得到多重结果:

%~dpI – 仅将 %I 扩充到一个驱动器号和路径
%~nxI – 仅将 %I 扩充到一个文件名和扩展名
%~fsI – 仅将 %I 扩充到一个带有短名的完整路径名
%~dp$PATH:i – 查找列在路径环境变量的目录,并将 %I 扩充
到找到的第一个驱动器号和路径。
%~ftzaI – 将 %I 扩充到类似输出线路的 DIR

在以上例子中,%I 和 PATH 可用其他有效数值代替。%~ 语法用一个有效的 FOR 变量名终止。选取类似 %I 的大写变量名比较易读,而且避免与不分大小写的组合键混淆。

转自:http://www.cnblogs.com/markor/archive/2007/06/04/771337.html

=======================example

echo process %1
set SERVER="APLOI2"

@echo off

set SQLPATH=test
echo process %SQLPATH%

for /f  %%f in (GCDTest.ctl) do  (
  
  for /f "tokens=1-2 delims=." %%1 in ("%%f") do (
    if not "%%2"=="" (
     if exist "../src/GCD/%%2/%%f"  (
      echo "execute ../src/GCD/%%2/%%f"
      echo exit |sqlplus gcd/system11@%SERVER% @"../src/GCD/%%2/%%f"
     )
    )
  )
)

pause

DOS 中for遍历文件内容相关推荐

  1. python中for循环在遍历文件内容时的问题

    f1= open(file1) f2= open(file2) for f1_line in f1:f2_line = f2.readline() f1= open(file1) f2= open(f ...

  2. java中读取properties文件内容五种方式

    一.背景 最近,在项目开发的过程中,遇到需要在properties文件中定义一些自定义的变量,以供java程序动态的读取,修改变量,不再需要修改代码的问题.就借此机会把Spring+SpringMVC ...

  3. 五种方式让你在java中读取properties文件内容不再是难题

    2019独角兽企业重金招聘Python工程师标准>>> 方式1.通过context:property-placeholder加载配置文件jdbc.properties中的内容 < ...

  4. python文本格式上一日_一日一技:在 Python 中快速遍历文件

    一日一技:在 Python 中快速遍历文件 摄影:产品经理 厨师:产品经理 当我们要在一个文件夹及其子文件夹里面寻找特定类型的文件,我们可能会这样写代码: 没有子文件夹时 import os all_ ...

  5. Dos中重定向与文件追加

    在Dos中可以通过">",来重定向输出的内容,通过">>"将输出的内容追加到文件中. 例如,执行以下命令: dir aaa.txt 这会将当前 ...

  6. linux中vi修改文件内容,linux VI模式下批量修改文件内容

    1.         :s/vivian/sky/ 替换当前行第一个 vivian 为 sky :s/vivian/sky/g 替换当前行所有 vivian 为 sky 2.         :n,$ ...

  7. android 组装xml,Android中组装xml文件内容

    在Android开发中经常遇到组装xml格式数据的需求,下面是解决方法,希望给大家带来帮助. 下面这段xml文件内容是我们的需求. zhangsan 26 lisi 25 下面是组装xml文件内容的代 ...

  8. python遍历文件内容_Python四种逐行读取文件内容的方法

    下面是四种Python逐行读取文件内容的方法, 并分析了各种方法的优缺点及应用场景,以下代码在python3中测试通过, python2中运行部分代码已注释,稍加修改即可. 方法一:readline函 ...

  9. 在html中显示word,如何在浏览器网页中显示word文件内容

    把word文件读到byte[]中,再Response.OutputStream.Write(bytes)到客户端去 Page_Load事件中写: //FileStream   fs   =   new ...

最新文章

  1. Spring MVC 学习 之 - 拦截器
  2. 背完这444句英语,你的口语绝对不成问题了
  3. char varchar java_在数据库中varchar与char的区别
  4. SpringCloudGateway静态路由配置
  5. WPF/E CTP Quick Start - 第五部分:公有图形属性(翻译)
  6. 冒泡排序 C++实现
  7. mysql如何只查询表中的前几条数据?多表查询前提了解
  8. 171.Excel表列序号
  9. 销售管理系统java sql_java+sqlserver商品销售管理系统的设计与实现
  10. 通达信最新 行情服务器,【图】我是如何打造普通行情比l2还快速的通达信行情服务器_股票公式,股票软件,股票论坛,炒股公式,股票_股票软件技术交流论坛_理想论坛 - 股票论坛...
  11. how to use 1checker_vim command
  12. 使用python绘制常用的图表
  13. 软件界面交互式设计注意事项
  14. 《深入理解计算机系统》:Cache Lab
  15. visio跨职能流程图带区背景及大小及改变格式 (转)
  16. 心蓝android版本,心蓝抢票app-心蓝抢票软件预约 _5577安卓网
  17. 如何在 Java 中实现最小生成树算法
  18. 全国计算机三级嵌入式必背总结资料
  19. 计算机基础知识综合参考书,计算机基础知识综合参考-20210411123539.pdf-原创力文档...
  20. [iOS]-KVO+KVC

热门文章

  1. python实现中文字符繁体和简体中文转换
  2. 《信息学奥赛一本通》 高精度加法。输入两个正整数,求它们的和。
  3. Vue.js的基本使用 学习笔记
  4. Linux(四) 用户、用户组
  5. 【Linux网络编程】组播
  6. 【Linux】一步一步学Linux——file命令(37)
  7. C语言设备管理器作业,你知道到吗,C语言竟是如何调用硬件的?
  8. android studio 反编译修改versioncode,在android studio 中修改versioncode 跟versionname(示例代码)...
  9. window部署DM8的DEM系统
  10. Codeforces 1480A. Yet Another String Game (阅读理解题)