How do I count all the files recursively through directories

161,440

Solution 1

find . -maxdepth 1 -type d | while read -r dir
do printf "%s:\t" "$dir"; find "$dir" -type f | wc -l; done

Thanks to Gilles and xenoterracide for safety/compatibility fixes.

The first part: find . -maxdepth 1 -type d will return a list of all directories in the current working directory.  (Warning: -maxdepth is a GNU extension and might not be present in non-GNU versions of find.)  This is piped to...

The second part: while read -r dir; do (shown above as while read -r dir(newline)do) begins a while loop – as long as the pipe coming into the while is open (which is until the entire list of directories is sent), the read command will place the next line into the variable dir. Then it continues...

The third part: printf "%s:\t" "$dir" will print the string in $dir (which is holding one of the directory names) followed by a colon and a tab (but not a newline).

The fourth part: find "$dir" -type f makes a list of all the files inside the directory whose name is held in $dir. This list is sent to...

The fifth part: wc -l counts the number of lines that are sent into its standard input.

The final part: done simply ends the while loop.

So we get a list of all the directories in the current directory. For each of those directories, we generate a list of all the files in it so that we can count them all using wc -l. The result will look like:

./dir1: 234
./dir2: 11
./dir3: 2199
...

Solution 2

Try find . -type f | wc -l, it will count of all the files in the current directory as well as all the files in subdirectories. Note that all directories will not be counted as files, only ordinary files do.

Solution 3

Here's a compilation of some useful listing commands (re-hashed based on previous users code):

List folders with file count:

find -maxdepth 1 -type d | sort | while read -r dir; do n=$(find "$dir" -type f | wc -l); printf "%4d : %s\n" $n "$dir"; done

List folders with non-zero file count:

find -maxdepth 1 -type d | sort | while read -r dir; do n=$(find "$dir" -type f | wc -l); if [ $n -gt 0 ]; then printf "%4d : %s\n" $n "$dir"; fi; done

List folders with sub-folder count:

find -maxdepth 1 -type d | sort | while read -r dir; do n=$(find "$dir" -type d | wc -l); let n--; printf "%4d : %s\n" $n "$dir"; done

List folders with non-zero sub-folder count:

find -maxdepth 1 -type d | sort | while read -r dir; do n=$(find "$dir" -type d | wc -l); let n--; if [ $n -gt 0 ]; then printf "%4d : %s\n" $n "$dir"; fi; done

List empty folders:

find -maxdepth 1 -type d | sort | while read -r dir; do n=$(find "$dir" | wc -l); let n--; if [ $n -eq 0 ]; then printf "%4d : %s\n" $n "$dir"; fi; done

List non-empty folders with content count:

find -maxdepth 1 -type d | sort | while read -r dir; do n=$(find "$dir" | wc -l); let n--; if [ $n -gt 0 ]; then printf "%4d : %s\n" $n "$dir"; fi; done

Solution 4

Try:

find /path/to/start/at -type f -print | wc -l

as a starting point, or if you really only want to recurse through the subdirectories of a directory (and skip the files in that top level directory)

find `find /path/to/start/at -mindepth 1 -maxdepth 1 -type d -print` -type f -print | wc -l

Solution 5

du --inodes

I'm not sure why no one (myself included) was aware of:

du --inodes
--inodes
      list inode usage information instead of block usage

I'm pretty sure this solves the OP's problem. I've started using it a lot to find out where all the junk in my huge drives is (and offload it to an older disk).

Further info

If you DON'T want to recurse (which can be useful in other situations), add

-S, --separate-dirs
Share:
161,440

Related videos on Youtube

xenoterracide
Author by

xenoterracide

Former Linux System Administrator, now full time Java Software Engineer.

Updated on September 17, 2022

Comments

  • xenoterracide
    xenoterracide over 1 year

    I want to see how many files are in subdirectories to find out where all the inode usage is on the system. Kind of like I would do this for space usage

    du -sh /*
    

    which will give me the space used in the directories off of root, but in this case I want the number of files, not the size.

    • Admin
      Admin over 13 years
    • Admin
      Admin over 13 years
      I think that "how many files are in subdirectories in there subdirectories" is a confusing construction. If more clearly state what you want, you might get an answer that fits the bill.
    • Admin
      Admin over 13 years
      @Steven feel free to rewrite it... I thought my example of du -sh /* made it pretty clear how I wanted the count to work. same thing, just count the files not the bytes.
    • Admin
      Admin over 13 years
      As you mention inode usage, I don't understand whether you want to count the number of files or the number of used inodes. The two are different when hard links are present in the filesystem. Most, if not all, answers give the number of files. Don't use them on an Apple Time Machine backup disk.
    • Admin
      Admin over 13 years
      @mouviciel this isn't being used on a backup disk, and yes I suppose they might be different, but in the environment I'm in there are very few hardlinks, technically I just need to get a feel for it. figure out where someone is burning out there inode quota.
    • Admin
      Admin over 13 years
      @mouviciel of course feel free to suggest a way to get the actual inode count
    • Admin
      Admin almost 6 years
      du should provide a builtin feature for this.
    • Admin
      Admin over 4 years
      @SridharSarnobat, ncdu does have a builtin feature for this, see answer below :)
    • Admin
      Admin over 4 years
      Actually I have since realized that du provides pretty much a solution built in.
  • Johan
    Johan over 13 years
    +1 for something | wc -l ... word count is such a nice little tool
  • xenoterracide
    xenoterracide over 13 years
    yeah but this only does 1 directory.... I'd like to get the count for all directories in a directory, and I don't want to run it seperately each time... of course I suppose I could use a loop... but I'm being lazy.
  • Didier Trosset
    Didier Trosset over 13 years
    find works recursively through all sub directories by default. If you want it to work in multiple locations, you can specify all of them between find and -type.
  • xenoterracide
    xenoterracide over 13 years
    that second one certainly doesn't work.... I tried it on /home . I got 698035 . I should see about 6 numbers.
  • xenoterracide
    xenoterracide over 13 years
    way too recursive... I only want to see the top level, where it totals everything underneath it. totaled... this ends up printing every directory.
  • Brian Rasmussen
    Brian Rasmussen over 13 years
    @xenoterracide: Try adding -maxdepth 1 immediately after the first find. If you want to include the number of subdirectories in your count, remove the -type f at the end (that should have really been ! -type d anyway, so that all non-directory files would have been included).
  • Cry Havok
    Cry Havok over 13 years
    It works for me - are you sure you only have 6 files under /home? I'd be 100% certain you don't.
  • Gilles 'SO- stop being evil'
    Gilles 'SO- stop being evil' over 13 years
    Always use read -r as plain read treats backslashes specially. Then echo -en "$dir:\t" will again mangle backslashes; a simple fix is to use printf '%s:\t' "$dir" instead. Next, $dir should be "$dir" (always use double quotes around variable substitutions).
  • xenoterracide
    xenoterracide over 13 years
    @Cry I have maybe 6 directories... not 6 files
  • xenoterracide
    xenoterracide over 13 years
    modified per @Giles suggestions find -maxdepth 1 -type d | while read -r dir; do printf "%s:\t" "$dir"; find "$dir" | wc -l; done
  • Gilles 'SO- stop being evil'
    Gilles 'SO- stop being evil' over 13 years
    Good idea taking hard links into account. Assuming GNU find, you don't need so many steps: find -printf '%i\n' | sort -u | wc -l. If you wanted to be portable, you'd need find . -exec ls -id {} + | cut … instead.
  • xenoterracide
    xenoterracide over 13 years
    I'm adding sort -n -r -k2 to the end of this, for lots of directories, so that I know where the most usage is
  • DolphinDream
    DolphinDream about 11 years
    And btw.. if you want to have the output of any of these list commands sorted by the item count .. pipe the command into a sort : "a-list-command" | sort -n
  • Krzysztof Boduch
    Krzysztof Boduch almost 10 years
    The fourth part: find "$dir" makes a list of all the files inside the directory name held in "$dir". You forgot to add -type f to make it list files: find -maxdepth 1 -type d | while read -r dir; do printf "%s:\t" "$dir"; find "$dir" -type f | wc -l; done
  • Arsen Karapetjan
    Arsen Karapetjan almost 7 years
    where do I write the name of the root directory?
  • MrSpreadsheet
    MrSpreadsheet almost 7 years
    I'm not getting this to work on macOS Sierra 10.12.5. illegal option -- m in the find command. I changed it to find . -maxdepth ... and got it to work.
  • Pablo A
    Pablo A over 6 years
    @xenoterracide you might have dirs with spaces, maybe better setting tab as delimiter sort -rt $'\t' -k 2,2 -V. Also 2>/dev/null after wc pipe to get rid of permission errors.
  • x-yuri
    x-yuri about 5 years
    lol, this must be the top-most accepted answer :)
  • x-yuri
    x-yuri about 5 years
    Why do you count only files? Directories take inodes as well as files. And well, the directory itself also takes an inode, but that doesn't affect the result much. Anyways, the other answer must be top-most and accepted.
  • vstepaniuk
    vstepaniuk over 4 years
    all those if's could be easily replaced with find [-not] -empty
  • sglessard
    sglessard over 4 years
    On Mac OS, it also counts the .DS_Store inside each directory. You can exclude them with the -type f ! -iname ".*" find parameter. You could also want to exclude files starting by ~*.
  • CervEd
    CervEd about 3 years
    not in freebsd :(
  • Sridhar Sarnobat
    Sridhar Sarnobat about 3 years
    I've never used BSD but did you try installing coreutils? I think that gives the GNU version of du. freshports.org/sysutils/coreutils
  • Kvothe
    Kvothe over 2 years
    Just to be clear: Does it count files in the subdirectories of the subdirectories etc...?
  • herohuyongtao
    herohuyongtao over 2 years
    @Kvothe Yes, recursively. :)
  • netawater
    netawater over 2 years
    @DolphinDream thanks, sort -n is good