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

I would like a BASH command to list just the count of files in each subdirectory of a directory.

E.g. in directory /tmp there are dir1, dir2, ... I'd like to see :

`dir1` : x files 
`dir2` : x files ...
share|improve this question
up vote 6 down vote accepted

Assuming you want a recursive count of files only, not directories and other types, something like this should work:

find . -maxdepth 1 -mindepth 1 -type d | while read dir; do
  printf "%-25.25s : " "$dir"
  find "$dir" -type f | wc -l
done
share|improve this answer
    
Also, I get "find: warning: you have specified the -maxdepth option after a non-option argument -type, but options are not positional (-maxdepth affects tests specified before it as well as those specified after it). Please specify options before other arguments." – jldupont Sep 14 '12 at 21:38
2  
Both answers given so far will give incorrect results in the unlikely case that there are files whose names include newline characters. You can handle that with a find ... -print0 | xargs -0 .... – Scott Sep 14 '12 at 21:57
    
@jldupont: move the depth arguments before the ´-type d´, I've edited the answer. – Thor Sep 14 '12 at 22:58
    
Yes, and let me add the information that this excellent solution will not take any external variables and thus will work with bash alias!! – syntaxerror Nov 25 '14 at 13:07

This task fascinated me so much that I wanted to figure out a solution myself. It doesn't even take a while loop and MAY be faster in execution speed. Needless to say, Thor's efforts helped me a lot to understand things in detail.

So here's mine:

find . -maxdepth 1 -mindepth 1 -type d -exec sh -c 'echo "{} : $(find "{}" -type f | wc -l)" file\(s\)' \;

It looks modest for a reason, for it's way more powerful than it looks. :-)

However, should you intend to include this into your .bash_aliases file, it must look like this:

alias somealias='find . -maxdepth 1 -mindepth 1 -type d -exec sh -c '\''echo "{} : $(find "{}" -type f | wc -l)" file\(s\)'\'' \;'

Note the very tricky handling of nested single quotes. And no, it is not possible to use double quotes for the sh -c argument.

share|improve this answer

Using find is definitely the way to go if you want to count recursively, but if you just want a count of the files directly under a certain directory:

ls dir1 | wc -l

share|improve this answer
    
I don't want to do this for each of the 1000's of directories I've got there... – jldupont Sep 14 '12 at 21:37
    
Then use xargs. ls -d */ | xargs -n1 ls | wc -l (Use the answer you accepted if it already works, though! This is just And Now You Know.) – jrajav Sep 14 '12 at 21:41
    
your proposal didn't show up any results in many seconds whereas the answer I accepted did. – jldupont Sep 15 '12 at 8:03
    
@jrajav this approach absolutely fails for directories with whitespace in them. This is why find is so important. (let alone -print0 and xargs -0, already pointed out by Scott in the other answer) – syntaxerror Nov 25 '14 at 13:03

What I use... This makes an array of all the subdirectories in the one you give as a parameter. Print the subdirectory and the count of that same subdirectory until all the subdirectories are processed.

#!/bin/bash    
directories=($(/bin/ls -l $1 | /bin/grep "^d" | /usr/bin/awk -F" " '{print $9}'))

for item in ${directories[*]}
    do
        if [ -d "$1$item" ]; then
            echo "$1$item"
            /bin/ls $1$item | /usr/bin/wc -l
        fi
    done
share|improve this answer

You must log in to answer this question.

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