Super User is a question and answer site for computer enthusiasts and power users. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

How would I go about finding all the folders in a directory than contain less than x number of .flac files?

share|improve this question
up vote 8 down vote accepted
  • For every subdirectory, print the subdirectory name if there are at most 42 .flac files in the subdirectory. To execute a command on the directories, replace -print by -exec … \;. POSIX compliant.

    find . -type d -exec sh -c 'set -- "$0"/*.flac; [ $# -le 42 ]' {} \; -print
    

    Note that this command won't work to search for directories containing zero .flac files ("$0/*.flac" expands to at least one word). Instead, use

    find . -type d -exec sh -c 'set -- "$0"/*.flac; ! [ -e "$1" ]' {} \; -print
    
  • Same algorithm in zsh. **/* expands to all the files in the current directory and its subdirectories recursively. **/*(/) restricts the expansion to directories. {.,**/*}(/) adds the current directory. Finally, (e:…:) restricts the expansion to the matches for which the shell code returns 0.

    echo {.,**/*}(/e:'set -- $REPLY/*.flac(N); ((# <= 42))':)
    

    This can be broken down in two steps for legibility.

    few_flacs () { set -- $REPLY/*.flac(N); ((# <= 42)); }
    echo {.,**/*}(/+few_flacs)
    

Changelog:
​• handle x=0 correctly.

share|improve this answer
    
The first command prints all the subdirectories. $# is always at least 1 hence [ $# -le 42 ] is true when there are no flac files in the subdirectory. – cYrus Sep 19 '10 at 10:45
    
@cYrus: If there are no flac files, there are fewer than 42 flac files. Ok, I should have mentioned that my solutions only work for 42 > 0, so they won't work to search for directories containing no flac files (you need a different, simpler command). – Gilles Sep 19 '10 at 11:43
    
I'm not talking about searching directories without flac files (x=0). I was saying that if a directory contains no flac files $# is 1 because $1 is literally path-to-dir/*.flac (as there's no expansion) the directory is printed anyway. It's just a different point of view, I'm assuming that a directory without flac files doesn't match the request. – cYrus Sep 19 '10 at 15:58

Replace $MAX with your own limit:

find -name '*.flac' -printf '%h\n' | sort | uniq -c | while read -r n d ; do [ $n -lt $MAX ] && printf '%s\n' "$d" ; done

Note: This will print all the subdirectories with a number of .flac files between 0 and $MAX (both excluded).

share|improve this answer
2  
Make that read -r n d in case directory names contain backslashes, and printf "%s "$d" in case directory names contain whitespace or -\['"\\`. – Gilles Sep 18 '10 at 23:48
    
Thanks for the -r, I really missed that! But I can't see any problem with echo, it correctly works with directories like: st r\a \`n-[g\"e – cYrus Sep 19 '10 at 0:30
    
sorry, wrong set of special characters. I should have said -*?\\[. Try creating two directories called foo and f*, with f* matching. Or a directory called foo bar (two spaces). Or (depending on your shell) a directory called -e or -n. – Gilles Sep 19 '10 at 11:41
    
A directory called -e... evil! – cYrus Sep 19 '10 at 16:02
1  
To avoid any issues with glob substitutions you should use -name '*.flac'. – Cristian Ciupitu Sep 19 '10 at 16:21

You must log in to answer this question.

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