Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

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!

share|improve this question

2 Answers 2

up vote 3 down vote accepted

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.

share|improve this answer
    
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 '12 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.) –  grawity Feb 20 '12 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 '12 at 21:57

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 needings, if it's not what you exactly want.

share|improve this answer
    
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 '12 at 19:48
1  
Will definitely break on spaces in file names, also beware of globbing characters when using $x again. –  slhck Feb 20 '12 at 21:44

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.