2

I want to list the number of directories under each subdirectory tree of the present directory. As there are too many directories, I can't go into individual directories and check. I would like to produce a report something like the one shown in the following picture:

enter image description here

The issue is: my server is giving some warning that the maximum limit of creating directories is reached. So I wanted to know which directory in my parent directory has the maximum sub-directories (excluding files),

7
  • A small change: where in the pic it says -dir1 -- 8000 (total count of only dirs including all sub directories,no files)..
    – MostWanted
    Jul 17, 2015 at 13:01
  • possible duplicate of Where are my inodes going? Jul 17, 2015 at 23:10
  • Are you concerned about reaching the inode limit, the path length, or something else? Jul 17, 2015 at 23:49
  • All these answers, not even a single explanation of what is doing what. Magic is magic indeed.
    – user123418
    Jul 18, 2015 at 1:51
  • I am getting an error in /var/adm/messages "vxfs: [ID 702911 kern.warning] WARNING: msgcnt 5555 mesg 128: V-2-128: number of links reached vx_maxlink for inode 53685 on filesystem". And on searching about it i found out that it is due to the number of sub-directories in FS reaching a limit 32k.
    – MostWanted
    Jul 21, 2015 at 15:30

5 Answers 5

1

Pure ksh93 solution:

FIGNORE='@(.|..)'
for dir in */; do a=( "$dir"/**/* ); printf "%s\t%s\n" "$dir:" "${#a[*]}"; done

Result from /usr/src:

linux-3.17.7-gentoo/:   561
linux-3.5.7-gentoo/:    517
linux-3.7.10-gentoo/:   505
linux-3.7.9-gentoo/:    513
linux-3.8.13-gentoo/:   551
linux-4.0.5-gentoo/:    1849
6
  • this commands seems to be giving total number of files + directories. can you modify it just to give directories(and all the sub-directories under it)
    – MostWanted
    Jul 21, 2015 at 15:45
  • @MostWanted Just remove double dots glob: for dir in */; do a=( "$dir"/* ); printf "%s\t%s\n" "$dir:" "${#a[*]}"; done
    – jimmij
    Jul 21, 2015 at 17:56
  • This command didn't give me the right output. Might be it was not checking under all the levels of the sub-directories. I have explained the question with an example image. Can you please check and provide the new command.
    – MostWanted
    Jul 29, 2015 at 21:57
  • @MostWanted Which shell are you using? This command gives me right answer on bash and zsh. I don't have ksh at hand to check. The glob **/* descent into all subdirectories recursively so will give you total number of files and directories. You may need to set some option to make ** work, as setopt -s globstar in bash.
    – jimmij
    Jul 29, 2015 at 23:12
  • my server uses bash..
    – MostWanted
    Jul 30, 2015 at 18:27
1

You could find the toplevel directories first, then use a second find, to count the number of files and directories within the toplevel directory:

$ for dir in $(find . -maxdepth 1 ! -path . -type d | sort); \
      do echo -n "$dir " && find $dir ! -path . | wc -l ; done
./adir 1151
./anotherdir 140
./623de41e44 280
./examples 154
...
1

Will something like this suit your need:

The path /boot is used for sample demonstration. Change it to the directory you need.

for DIR in $(find /boot/* -maxdepth 1 -type d)
do
    printf "%40s: %10d\n" "${DIR}" $(find ${DIR}|wc -l)
done

Output:

                          /boot/grub:        282
                    /boot/grub/fonts:          2
                  /boot/grub/i386-pc:        272
                   /boot/grub/locale:          4
                    /boot/lost+found:          1
0
0

try

  find * -print | awk -F/ '{c[$1]++;} END { for (c2 in c) printf "-%s -- %d\n",c2,c[c2] ;} '

where

  • find from directory above the ones you want to sum up
  • awk will count top level dir and file and sum up at the end.
0

The following little loop will list a count of all files (excepting symlinks) in child directories of . which exist on the same filesystem as the child directory.

for d in ./* ./.[!.]* ./..?*
do  ! [ -h "$d" ]  &&
      cd "$d" 2>&3 || continue
      printf "%s:\t" "$d"
      find .//. -xdev -depth ! -type l |
      grep -c '^\.//\.'
      cd ..
done  3>/dev/null

You must log in to answer this question.

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