10.9 对搜索到的每个文件执行命令

find -exec

现在进入find命令真正展露其威力的领域:能够对搜索到的文件再执行命令。在列出用于限制搜索的选项(例如-name-type-user)后,再附加一个-exec选项,后面跟上要为找到的每个文件执行的命令。用{}符号来代表找到的每个文件,并用\对分号(;)进行转义以作为命令的结束,这样shell就不会把它理解为命令栈的标志(有关命令栈,可以参见第4章中的相关介绍)。

例如,上一节中发现music盘里的某些文件是以MP3结尾的。因为更喜欢小写字母的扩展名,所以需要把所有出现MP3的地方都转换成mp3,保持文件的统一性。用find命令的-exec选项完成这个操作。首先,先确保选中的文件是以MP3结尾的,如下所示:

  1. $ find . -name "Robert_Johnson*MP3"
  2. ./Blues/Robert_Johnson/Judgment_Day.MP3
  3. ./Blues/Robert_Johnson/Dust_My_Broom.MP3
  4. ./Blues/Robert_Johnson/Hellhound_On_My_Trail.MP3

接下来,用带有-exec选项的find命令修改文件扩展名。和-exec选项一起使用的程序是rename,它可以修改文件名中的某些部分:

  1. $ find . -name " *MP3" -exec rename 's/MP3/mp3/g' {} \;

rename命令后面是关于文件名如何变化的指令,其格式为:s/old/new/gs代表substitute(代表),g代表global(目标)]。现在来看看命令能否起到作用:

  1. $ find . -name "Robert_Johnson*MP3"
  2. $ ls -1 Blues/Robert_Johnson/
  3. Hellhound_On_My_Trail.mp3
  4. Judgment_Day.mp3
  5. Dust_My_Broom.mp3
  6. Love_in_Vain.mp3
  7. Me_and_the_Devil_Blues.mp3

这个命令看起来是奏效了。接下来试试另一种情况下的类似处理。在上一节的搜索结果中有很多m3u(或播放列表)文件。遗憾的是,这些文件的文件名中很多都有空格,这是要尽量避免的。首先,先找到文件名中有空格的m3u文件列表。搜索* *m3u,也就是用两个通配符把一个空格围起来,就能找到文件名中包含空格的文件,如下所示:

  1. $ find . -name "* *m3u"
  2. ./Christmas/Christmas With The Rat Pack.m3u
  3. ./Christmas/Holiday_Boots_4_Your_Stockings.m3u
  4. ./Classical_Baroque/Handel/Chamber Music.m3u
  5. ./Classical_Opera/Famous Arias.m3u
  6. ./Doo_Wop/Doo Wop Box.m3u
  7. ./Electronica/Aphex_Twin/I Care Because You Do.m3u

现在,先搜索一下文件名中有空格的m3u文件,当找到这样的文件时,就能够对它运行rename命令。在此,为了修复这个问题,用_来取代\ (需要对空格进行转义,这样find命令才能够明白要搜索的内容,而shell也不会混淆各个命令),如下所示:

  1. $ find . -name "* *m3u" -exec rename 's/\ /_/g' {}
  2. \;
  3. $ find . -name "* *m3u"
  4. $

命令像所期待的那样运行。

说明 注意,在对文件执行命令之前,必须先明确要修改哪些文件。这是一种谨慎处事的好习惯,谁都不想修改错误的文件!