From an entire directory structure I would like to output all the owners and how many files belong to each owner.

I would like an output like this:

| alex  |   3 |
| liza  | 345 |
| harry | 564 |
| sally |  23 |

How can I do this in bash?


This won't draw the pretty lines but...


for _user in `ls /home`
    _count=`ls -R /home/$_user/ | wc -l`
    echo "$_user = $_count"
  • thanks so much! im actually using cygwin to do this on a windows file server, – l--''''''---------'''''''''''' Feb 1 '13 at 19:46
  • This will be inaccurate as the ls -R output will have a blank line for each new directory. Parsing ls is usually unreliable. Also you're missing out on hidden "dot" files (.hidden). – gertvdijk Feb 1 '13 at 20:52

Consider using the Linux quota system. You'll have to enable it first and get it initialized, but it will require a lot less resources for creating a report.

  1. Install the quota package.
  2. Add the usrquota mount option to the file system in /etc/fstab.
  3. Remount or reboot the file system.
  4. Do the initial quota scan by running quotacheck -avug.
  5. Run repquota to list the usage. The File limits (used) column lists the amount of 'files' per user. However, it's not quite the same as the amount of actual files, but it's the number of inodes.

                            Block limits                File limits
    User            used    soft    hard  grace    used  soft  hard  grace
    root      --   80088       0       0          12025     0     0       
    daemon    --       8       0       0              3     0     0       
    man       --     172       0       0             17     0     0       

To get a new report on a later time, it's only required to run repquota and this will run a lot quicker than running find all over again!

Note: it's not needed to set actual quota limits - just use it for reporting.


I would suggest to use find and wc in a for-loop:

users=`getent passwd | awk -F: '{print $1}'`
for user in $users
    echo -n "file count for $user: "
    find / -user $user -type f | wc -l


  • find is recursive by default.
  • You may want to prepend the find line with sudo in order to have the privileges for reading all directories. Or run the complete script as root.
  • It now limits to listings of files by the -type f filter. Remove that if you want to count directories too.
  • It's not terribly efficient, as it's first listing all names, while wc -l then just counts the number of newlines.

Parsing ls -R is inaccurate for several reasons. Firstly, it lists directory entries twice. Secondly, it leaves an additional blank line while it descends into directories. Thirdly, you'll need to pass -a to count hidden files. And finally, it won't be possible to filter directories.

See the demo below:

mkdir d1 d2 d3
touch a b c d1/a d2/a d3/a
├── a
├── b
├── c
├── d1
│   └── a
├── d2
│   └── a
└── d3
    └── a

3 directories, 6 files

find . | wc -l

find . -type f | wc -l

ls -R | wc -l

ls -R | cat -   # to show why the number was 16



  • The for-loop requires a list of user names, but this can be generated based on the directories in /home/ by replacing the hard-coded user names with $(ls /home). – iBelieve Feb 1 '13 at 20:29
  • @iBelieve Users with a home folder outside /home will not be listed then. And, moreover, a user's home folder does not have to match the username. So, I've added it "the right way" by using passwd. – gertvdijk Feb 1 '13 at 20:48

Based on Ed Manet's answer, this will print the lines around the file counts:


echo "+---------------+-------+"
for _user in `ls /home`
    _count=`ls -R /home/$_user/ | wc -l`
    printf "| $_user\t| $_count\t|\n"
echo "+---------------+-------+"

Note that this works by counting the files in each user's home directory, so it can only scan the /home/ directory, and also it won't work correctly if one user has files in another user's directory.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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