Take the 2-minute tour ×
Ask Ubuntu is a question and answer site for Ubuntu users and developers. It's 100% free, no registration required.

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?

share|improve this question
add comment

4 Answers

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

#!/bin/bash

for _user in `ls /home`
do
    _count=`ls -R /home/$_user/ | wc -l`
    echo "$_user = $_count"
done
share|improve this answer
    
thanks so much! im actually using cygwin to do this on a windows file server, –  Артём Царионов 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
add comment

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.

share|improve this answer
add comment

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

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

Notes:

  • 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
tree
.
├── a
├── b
├── c
├── d1
│   └── a
├── d2
│   └── a
└── d3
    └── a

3 directories, 6 files

find . | wc -l
11

find . -type f | wc -l
7

ls -R | wc -l
16

ls -R | cat -   # to show why the number was 16
.:
a
b
c
d1
d2
d3

./d1:
a

./d2:
a

./d3:
a
share|improve this answer
    
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
add comment

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

#!/bin/bash

echo "+---------------+-------+"
for _user in `ls /home`
do
    _count=`ls -R /home/$_user/ | wc -l`
    printf "| $_user\t| $_count\t|\n"
done
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.

share|improve this answer
add comment

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.