Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I want to know the total number of files on my server. Can this be done?

share|improve this question
2  
For a rough estimate (also counts directories) without scanning the entire file system, there is df -i. –  Simon Richter Apr 7 at 17:21
add comment

4 Answers 4

up vote 4 down vote accepted

Depending on what exactly you want to count, you are better doing this per filesystem rather than counting all files under root. Counting everything under root would also count /proc and /sys files which you may not want to include.

To count everything on the root filesystem using GNU find, you could do:

find / -xdev -type f -printf '\n' | wc -l

The -printf '\n' will just print a newline for every file found, instead of the filename. This way, there are no problems with filenames that contain newlines themselves and would count as multiple files.

With a POSIX find you could simply do:

find / -xdev -type f | wc -l

Or POSIXly and avoiding any file containing newlines from being counted twice:

{ printf 0; find / -xdev -type f -exec sh -c 'printf "+ $#"' sh {} +; echo; } | bc

Here each file becomes a different argument to sh which then prints the total number of arguments. In case more than one sh process is called, as will be the case for many files, each sh output is summed in bc.

Update

A simpler (but slower) POSIX solution:

find / -xdev -type f -exec printf '%s\0' {} + | tr '\n\0' '?\n' | wc -l

Update 2

As noted by @Gilles, using -type f with find only counts regular files. To also include device files, you could use -type f -o -type b -o -type c. To count directories as well, don't use any -type option.

Another point by Gilles was that files with multiple hard links will be counted as different files. This may not be desirable on a filsystem where, for example increment backup trees have been created by hardlinking unchanged files in a newer tree to those in an older one. To overcome this with GNU tools you could do:

find / -xdev -type f -printf '%i\n' | sort -u | wc -l

Using POSIX tools:

find / -xdev -type f -exec ls -iq {} + | sort -buk 1,1 | wc -l

No problems with newlines in filenames here since the -q option to ls means that it will replace them with ?.

share|improve this answer
    
The -n option to echo is not POSIX. Use the shell's printf. –  jordanm Apr 7 at 14:19
    
@jordanm, thanks, fixed. Also missed the dummy $0 argument for sh, without it the count will be one short for each sh run. –  Graeme Apr 7 at 14:29
    
Why -type f? The question asked for a count of files, not of regular files. Note that all of these methods count files multiple times if they have multiple hard links (excluding . and .. links to directories). –  Gilles Apr 7 at 20:06
    
@Gilles, good points, updated. –  Graeme Apr 7 at 22:08
    
@Graeme, Instead of sort -buk 1,1, can we do same thing just with just sort -buk 1? man sort says KEYDEF is F[.C][OPTS][,F[.C][OPTS]]. Because we sort by inode number, only field 1 seems to be enough. –  MS.Kim Apr 8 at 1:10
show 4 more comments

df -i / gives you the number of used inodes on the root filesystem (on filesystems that use inodes, which includes the ext2/ext3/ext4 family but not btrfs). This is the number of files on that filesystem, plus a few inodes that are preallocated for the use of fsck.

If you want the number of files in a directory tree, then you can use the following command:

du -a /some/directory | wc -l

Add the option -x to du if you don't want to traverse mount points, e.g. du -ax / | wc -l. Note that this will return a larger count if you have file names containing newlines (a bad idea, but not impossible).

Another way to count is

find /some/directory | wc -l

or, to cope with file names containing newlines, with GNU find (non-embedded Linux or Cygwin):

find /some/directory -printf . | wc -c

Add -xdev (e.g. find /some/directory -xdev -printf .) to skip mount points. Note that this directory entries, not files: if a file has multiple hard links, then each link is counted (whereas the df and du methods count files, i.e. multiple hard links to the same file are only counted once).

share|improve this answer
    
This a very good point. I dont know why i didnt make it, except that i must be getting senile, as i made the very same point only a few days ago. And thank you for pointing out the -f thing - thats an egregious error that i also made. You can handle all filenames with a little use of /./ though, newlines or no. unix.stackexchange.com/a/122871/52934 –  mikeserv Apr 7 at 23:59
add comment

UPDATE

This is the fastest method I can imagine that this can be done fully portably. I use tar below because it will automatically add hard linked files only once:

   find /./ -xdev ! -type d | tar -cf - - | tar -t | sed -n '\|^/\./|c.' | wc -l

portable and very fast:

find / -xdev | sed -n '/^[./]/c\.' | wc -l

I don't believe you do need all of the rest - though @Graeme was correct about the possible misses below. This, however, does not have the same shortcomings:

find /./ -xdev | sed -n '\|^/\./|c.' | wc -l

All you need to do is ensure a full path to root and you don't have to jump through all of the other hoops.

NOTE: As Gilles points out, using -type f is an egregious error. I have updated this post to reflect this.

Also for a more accurate count, you need only do:

du / --inodes -xs

Provided your tools are up to date, that will provide you with the exact number of files in your root filesystem. This can be used for any directory as well.

Here's a means of getting an exact count of all files in any filesystem or subdirectory excluding hardlinks with only very commonly available tools. First isolate target root with a mount --bind away:

mkdir /tmp/ls ; sudo mount -B / $_ ; cd $_

Next, count your files:

sudo ls -ARUi1 ./ | 
grep -o '^ *[0-9]*' | 
sort -un | 
wc -l

I did something very similar to this for another answer a few days ago - though that was a little more complicated because the goal was to sort by subdirectories containing the highest file counts - so the command there looks a little different than the one here. But this is still very fast, by the way.

Anyway, the heart of that is the ls command. It -Recursively searches the entire tree, listing -Almost-all -inodes -Unsorted at -1 file per line. Then we grep -only the inode [0-9]numbers, sort on -unique -numbers and wcount -lines.

share|improve this answer
1  
Still doesn't give any guarantees for awkwardly named files, although it does reduce the range of names that will fail. The overhead of counting the files should always be minimal compared to the find itself anyway. –  Graeme Apr 7 at 15:20
    
@Graeme It completely erases filenames entirely. In what case would it miss? As far as the overhead goes, it looks like your answer is invoking a shell per file? I need to look closer... –  mikeserv Apr 7 at 15:26
    
Filenames containing a newline before a dot would be counted twice. Files beneath a directory with a name ending in a newline would also be counted twice. The only robust way to exclude all edge cases with multiple filenames is to somehow pass each one as an argument or to have the names null separated (but POSIX tools rarely support this). –  Graeme Apr 7 at 15:36
    
@Graeme - you were right about possible failures, but i fixed it. –  mikeserv Apr 7 at 16:17
    
Ah, very good, find won't produce the /./ sequence anywhere else in the path. I will remember this trick. I think you can drop the backslash after the c since this is not part of a regex. –  Graeme Apr 7 at 16:36
show 8 more comments

From your root directory:

find . -type f | wc -l

You can change the path (here .) to whatever the directory you want to count the files in. If you don't want to go in subdirectories, add the option -maxdepth 1

share|improve this answer
    
Or from any directory, find / -type f ... –  fedorqui Apr 7 at 13:07
    
the form find wihtout a working directory precise is not posix –  Kiwy Apr 7 at 13:08
    
I indeed forgot to dot, I corrected it (typo). –  Laurent C. Apr 7 at 13:09
    
This will not work as file names can contain newline characters. –  Anthon Apr 7 at 13:18
1  
@JennyD or just -printf "\n", perhaps... –  Graeme Apr 7 at 15:21
show 2 more comments

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.