`

shell for 循环指令使用

阅读更多

来源地址: http://hi.bccn.net/space-21499-do-blog-id-13524.html

shell for 循环指令使用
2008-11-02 22:34

for可以使一些不支持通配符的命令对一系列文件进行操作。在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:proj elease.CVS ,但不会影响命令的执行效果。
2. 将某一文件内容或命令执行结果作为循环范围:
假如你有一个文件 todel.txt,里面是所有要删除的文件列表,现在你想将里面列出的每个文件都删掉。假设这个文件是每个文件名占一行,象这样:
    c: empa1.txt
    c: empa2.txt
    c: empsubdir3.txt
    c: empsubdir4.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: mp
    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:mp3Archived-18-01-A游鸿明-下沙游鸿明-01 下沙.mp3
    g:mp3Archived-18-01-A游鸿明-下沙游鸿明-02 21个人.mp3
    ......
    g:mp3Archived-18-01-A王菲-寓言王菲-阿修罗.mp3
    g:mp3Archived-18-01-A王菲-寓言王菲-彼岸花.mp3
    g:mp3Archived-18-01-A王菲-寓言王菲-不爱我的我不爱.mp3
    ......

如果我只要歌名(不要路径和".mp3"):
    游鸿明-01 下沙
    游鸿明-02 21个人
    ......
    王菲-阿修罗
    王菲-彼岸花
    王菲-不爱我的我不爱
    ......

那么可以用FOR命令:
    for /r g:mp3 %a in (*.mp3) do @echo %~na

凡是 %~ 开头的操作符,都是文件名的分离操作。具体请看 for /? 帮助。
本文举的例子有些可能没有实际用处,或可用其它办法完成。仅用于体现FOR可以不借助其它工具,仅用DOS命令组合,就可完成相当灵活的任务。
分享到:
评论

相关推荐

    【shell脚本】shell脚本之条件判断if、for与while循环(shell脚本基础学习二)

    for循环: for 变量名称 in 值1 值2 值3...... do 执行指令 done ------------------------- 1, 循环次数,和值有关 2, 循环时的变量,也和值有关 ------------------------- #!/bin/bash for i in {1..10} 多个值的...

    linux设置shell命令—–set

    set Linux set命令用于设置shell。 set指令能设置所使用shell的执行方式,可依照不同的需求来做设置。 语法 set 【选项】 【参数】 ...-l:记录for循环的变量名称 -m:使用监视模式 常用实例 直接

    set命令 设置shell

    set命令能设置所使用shell的执行方式,可依照不同的需求来做设置。 语法格式:set [参数] 常用参数: -a 标示已修改的变量,以供输出至环境变量 ...记录for循环的变量名称 -m 使用监视模式

    linux基础之Shell Script入门介绍

    1 Shell Scipt使用指令和基本程序设计结构写成的程序,可以完成复杂的处理流程 1.1 程序书写 代码如下:#!/bin/bash# Program:# This program shows “Hello Wrold” in your screen.# History:# 2013/2/3 on_1y ...

    Shell脚本中awk指令的用法

    语法格式:awk [选项] ‘指令’ 操作文件 常用选项:-F 指定分隔符,分隔符用””引起来 -v:var=value在awk程序开始之前指定一个值valu给变量var,这些变量值用于awk程序的BEGIN快 -f:后面跟一个保存了awk...

    shell脚本–awk的用法

    语法格式:awk [选项] ‘指令’ 操作文件 常用选项:-F 指定分隔符,分隔符用””引起来 -v:var=value在awk程序开始之前指定一个值valu给变量var,这些变量值用于awk程序的BEGIN快 -f:后面跟一个保存了awk程序的...

    Ubuntu权威指南(2/2)

    8.9.3 for循环的I/O重定向 222 8.10 Here文档 223 8.11 Shell函数 227 8.12 逻辑与和逻辑或并列结构 232 8.12.1 逻辑与命令并列结构 232 8.12.2 逻辑或命令并列结构 233 8.13 Shell数组 233 8.14 信号的捕捉与处理 ...

    Ubuntu权威指南(1/2)

    8.9.3 for循环的I/O重定向 222 8.10 Here文档 223 8.11 Shell函数 227 8.12 逻辑与和逻辑或并列结构 232 8.12.1 逻辑与命令并列结构 232 8.12.2 逻辑或命令并列结构 233 8.13 Shell数组 233 8.14 信号的捕捉与处理 ...

    RED HAT LINUX 6大全

    9.5.3 基本SSI指令 165 9.5.4 流控制 167 9.6 启动和停止服务器 167 9.6.1 手动启动服务器 167 9.6.2 /etc/rc.d httpd脚本 168 9.7 配置文件清单 170 9.8 小结 185 第10章 Internet新闻 186 10.1 Linux与新闻组 186 ...

    毕业设计里的程序源码查重-SI506-2020Winter:SI506课程材料(2020年冬季)

    指令编程语言是一种通用的、面向对象的、动态类型的、解释型语言,在开发人员和数据科学家中很流行。 学习目标 在入门级利用 Python 仔细分析计算问题 巧妙解决计算难题 快速调试运行时错误 高效处理数据 准备 SI ...

    ARM_Linux启动分析.pdf

    本文以Redhat 6.0 Linux 2.2.19 for Alpha/AXP为平台,描述了从开机到登录的 Linux 启动全过程。该文对i386平台同样适用。 一. Bootloader 在Alpha/AXP 平台上引导Linux通常有两种方法,一种是由MILO及其他类似的...

    编程新手真言......

    2.12 二进制指令与循环 66 2.13 所谓函数 67 2.14 所谓流程 68 2.15 为什么需要数据类型和数据结构 68 2.16 数据类型和数据结构是二种不一样的东西 69 2.17 为什么需要变量这些东东 69 2.18 面向类型化的设计和面向...

Global site tag (gtag.js) - Google Analytics