10.9 对搜索到的每个文件执行命令
find -exec
现在进入find
命令真正展露其威力的领域:能够对搜索到的文件再执行命令。在列出用于限制搜索的选项(例如-name
、-type
或-user
)后,再附加一个-exec
选项,后面跟上要为找到的每个文件执行的命令。用{}
符号来代表找到的每个文件,并用\
对分号(;)进行转义以作为命令的结束,这样shell就不会把它理解为命令栈的标志(有关命令栈,可以参见第4章中的相关介绍)。
例如,上一节中发现music盘里的某些文件是以MP3结尾的。因为更喜欢小写字母的扩展名,所以需要把所有出现MP3
的地方都转换成mp3
,保持文件的统一性。用find
命令的-exec
选项完成这个操作。首先,先确保选中的文件是以MP3
结尾的,如下所示:
$ find . -name "Robert_Johnson*MP3"
./Blues/Robert_Johnson/Judgment_Day.MP3
./Blues/Robert_Johnson/Dust_My_Broom.MP3
./Blues/Robert_Johnson/Hellhound_On_My_Trail.MP3
接下来,用带有-exec
选项的find
命令修改文件扩展名。和-exec
选项一起使用的程序是rename
,它可以修改文件名中的某些部分:
$ find . -name " *MP3" -exec rename 's/MP3/mp3/g' {} \;
rename
命令后面是关于文件名如何变化的指令,其格式为:s/old/new/g
[s
代表substitute(代表),g
代表global(目标)]。现在来看看命令能否起到作用:
$ find . -name "Robert_Johnson*MP3"
$ ls -1 Blues/Robert_Johnson/
Hellhound_On_My_Trail.mp3
Judgment_Day.mp3
Dust_My_Broom.mp3
Love_in_Vain.mp3
Me_and_the_Devil_Blues.mp3
这个命令看起来是奏效了。接下来试试另一种情况下的类似处理。在上一节的搜索结果中有很多m3u
(或播放列表)文件。遗憾的是,这些文件的文件名中很多都有空格,这是要尽量避免的。首先,先找到文件名中有空格的m3u文件列表。搜索* *m3u
,也就是用两个通配符把一个空格围起来,就能找到文件名中包含空格的文件,如下所示:
$ find . -name "* *m3u"
./Christmas/Christmas With The Rat Pack.m3u
./Christmas/Holiday_Boots_4_Your_Stockings.m3u
./Classical_Baroque/Handel/Chamber Music.m3u
./Classical_Opera/Famous Arias.m3u
./Doo_Wop/Doo Wop Box.m3u
./Electronica/Aphex_Twin/I Care Because You Do.m3u
现在,先搜索一下文件名中有空格的m3u文件,当找到这样的文件时,就能够对它运行rename
命令。在此,为了修复这个问题,用_
来取代\
(需要对空格进行转义,这样find
命令才能够明白要搜索的内容,而shell也不会混淆各个命令),如下所示:
$ find . -name "* *m3u" -exec rename 's/\ /_/g' {}
\;
$ find . -name "* *m3u"
$
命令像所期待的那样运行。
说明 注意,在对文件执行命令之前,必须先明确要修改哪些文件。这是一种谨慎处事的好习惯,谁都不想修改错误的文件!