Bash Shell循环中使用read

Bash Shell循环中使用read,你正在使用 Subversion 版本控制系统,其对应的可执行文件是 svn。(这个例子对于 CVS 来说也是大同小异。)检查目录子树状态,查看是否有文件被改动时,你会看到如下显示:

$ svn status bcb
M      bcb/amin.c
?      bcb/dmin.c
?      bcb/mdiv.tmp
A      bcb/optrn.c
M      bcb/optson.c
?      bcb/prtbout.4161
?      bcb/rideaslist.odt
?      bcb/x.maxc
$

? 起始的行代表 Subversion 尚不知晓的文件,通常是草稿文件或文件的临时副本。以 A 起始的行代表新添加的文件,以 M 起始的行代表自上次提交后又发生改动的文件。

要想清理该目录,最好是删除所有的草稿文件。

解决方案

while 循环的一种常见用法是读取文件和之前命令的输出。尝试下列命令:

svn status mysrc | grep '^?' | cut -c8- |
  while read FN; do echo "$FN"; rm -rf "$FN"; done

或者:

svn status mysrc |
while read TAG FN
do
    if [[ $TAG == \? ]]
    then
        echo $FN
        rm -rf "$FN"
    fi
done

讨论

这两个脚本的效果相同:删除 svn 报告其中带有 ? 标记的文件。同样的解决方案也适用于其他版本控制系统。

第一种方法是用多个子程序来实现(在如今处理器以 GHz 为单位进行计算的时代,这算不上什么大事),在典型的终端窗口中够写满一行。先用 grep 选择以 ? 起始(由 ^ 表示)的行。将 ^? 放进单引号中('^?')以避免 bash 解释其中具有特殊含义的字符。接着用 cut 提取从第 8 列开始(一直到行尾)的字符串。

如果没有输入,read 会返回非 0 值并停止循环。在此之前,它每次都会将读取到的文本行(其实也就是要删除的文件名)赋给变量 $FN。-rf 选项是以防待删除的未知文件是目录或只读文件。如果不希望删除文件时表现得如此极端,可以去掉这些选项。

第二个脚本更有 shell 的范儿,既不用 grep 进行搜索(使用的是 if 语句),也没用 cut 剪切(使用的是 read 语句)。我们还像在脚本文件中那样对其做了格式化。如果是在命令提示符下输入这些代码,你可以省略缩进,但作为文章中的示例,可读性远比少敲几个键更重要。

第二个脚本中的 read 将内容读入两个变量,看清楚,这次可不是一个。我们也要让 bash 将每行分成两部分:为首的字符和文件名。read 语句将输入行解析成若干单词(和 shell 命令行中的类似)。输入行的第一个单词赋给 read 语句中的第一个变量,第二个单词赋给第二个变量,以此类推。最后一个变量获得输入行中剩余的所有内容,即便其中不止一个单词。在这个例子中,$TAG 得到的第一个单词是字符(M、A 或 ?);空白字符用于分隔单词。变量 $FN 得到了行中剩余部分,也就是文件名,这一点在文件名中包含空白字符时尤为重要。(我们想要的可不是文件名中的第一个单词。)脚本接下来会删除相应的文件并进入下一次循环。

酷客网相关文章:

赞(0)

评论 抢沙发

评论前必须登录!