1

I'm trying to create a series of playlists on my MP3 player, running Rockbox, by finding a file matching a string, using find /cygdrive/g/MUSIC -type f -name "Search Criteria" | /cygdrive/g/PLAYLIST/Playlist Name.m3u8. When I search using $ find /cygdrive/g/Music -type f -name "*Theme*", my results are:

/cygdrive/g/Music/Movie Masterpieces/14 - 1900's Theme.ogg
/cygdrive/g/Music/Movie Masterpieces/02 - Deborah's Theme.ogg
/cygdrive/g/Music/Star Trek_ The Motion Picture [Disc 1]/01 - Ilia's Theme.ogg

However, I would like to be able to search for any folder and output the names of the files inside, for an output similar to:

/cygdrive/g/Music/Cult Themes/01 - The Avengers (1965).ogg       
/cygdrive/g/Music/Cult Themes/02 - Man In A Suitcase (1968).ogg  
/cygdrive/g/Music/Cult Themes/03 - The Saint (1962).ogg

I have access to both a Linux terminal, cygwin or Windows command prompt, and would be grateful for any solution, but if possible in one or two lines.

Edit: After receiving the a number of solutions, I've found the best solution was:

find /cygdrive/g/MUSIC -type d -iname "*theme*" -print -prune 
| xargs -d '\n' -I {} find {} -name '*.ogg'

This solution was able to complete the search the quickest, and whilst it may not be as brief as the first response, is still succinct. Thanks to all who responded!

2 Answers 2

3

The right way to process find output is not for, but to read it line by line:

find . -type d -iname '*themes*' -print -prune |
while read -r path; do
    find "$path" -name '*.ogg'
done

or

find . -type d -iname '*themes*' -print -prune |
xargs -d '\n' -I {} find {} -name '*.ogg'

or let find do it:

find . -type d -iname '*themes*' -exec find {} -name '*.ogg' \; -prune

-prune is a simple safeguard against cases where both a parent directory and a subdirectory match the -iname rule.

I skipped the traditional -print0 | xargs -d '\0' since filenames with newline characters are very, very unlikely to exist on a FAT32 filesystem.

3
  • You could also set IFS=$'\n' and then read line, but that breaks on wildcards too when you use the filename again, so … yeah. exec would be the most concise option.
    – slhck
    Feb 20, 2012 at 21:43
  • @slhck: read does not process wildcards, so I don't see how would it break when using read line. (The only place I can see is during expansion of the variable, which can be solved by double-quoting.) Feb 20, 2012 at 21:48
  • Yeah I meant expansion, it wasn't the case for your answer anyway. Just something that can be easily forgotten.
    – slhck
    Feb 20, 2012 at 21:57
1

Here is the way to search for a dir (eg. themes), and list all the .ogg files under it (recursively):

for x in $(find . -iname "*themes*"); do find $x -iname "*.ogg"; done

I think you can customize this example for your needs, if it's not what you exactly want.

2
  • That almost works, once brackets are added for x in $( find ... ); do ..., but does not work if folders have spaces in their names. Thanks for the quick response, if I get any further I'll put the solution up.
    – jClark94
    Feb 20, 2012 at 19:48
  • 1
    Will definitely break on spaces in file names, also beware of globbing characters when using $x again.
    – slhck
    Feb 20, 2012 at 21:44

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .