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.

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

2 Answers 2

up vote 6 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

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.