Execute a Command on Every Found File

find -exec

Now we enter the area in which find really shows off its power: the ability to execute commands on the files that it, uh, finds. After listing the options that help narrow down your searchsuch as -name, -type, or userappend -exec along with the commands you want to run on each individual file. You use the symbols {} to represent each file, and end your command with \ to escape the semicolon so your shell doesn't interpret it as an indication of command stacking (which we discussed in Chapter 4, "Building Blocks").

In the previous section, for example, we discovered that some of the files on the music drive ended with MP3. Since we prefer lowercase extensions, we need to convert all instances of MP3 to mp3 to make the files consistent. We can do this with the -exec option for find. First, let's verify that there are files that end with 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 

Let's use find with -exec to change the file extension. The program we can use with -exec is rename, which changes parts of filenames:

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

The rename command is followed with instructions for the name change in this format: s/old/new/g. (The s stands for "substitute," while the g stands for "global.") Now let's see if our command works:

$ 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 

The command appears to work. Let's try a similar process with another situation. In the previous section, we noticed that many of the results discovered were m3u, or playlist, files. Unfortunately, many of these files had spaces in the filenames, which we try to avoid. Let's first generate a list of m3u files that have spaces. We can search for * *m3u, which uses wildcards around a space to discover files that include spaces in their name:

$ 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 

Now let's find m3u files with spaces in their names; when one is found, we can run rename against it. We're substituting "\ " (we escape the space so that find understands what we're looking for and the shell doesn't get confused) with "_" to fix the problem:

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

The command worked as planned.


Note that before running commands on the files, we must always first figure out which files are going to be changed. That's just good prudence. You don't want to change the wrong files!

Linux Phrasebook
Linux Phrasebook
ISBN: 0672328380
EAN: 2147483647
Year: 2007
Pages: 288

Similar book on Amazon

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net