10

I would like to print the number of folders (recursive, excluding hidden folders) in a given CWD / current directory. What command, or series of commands can I use to ascertain this information?

3
  • (1) What do you mean by "a given root directory"? A Unix/Linux system has one root directory. (2) Have you made an attempt to solve this yourself? What have you tried? (Hint: How would you identify the folders in a given folder, and how would you count things?) Commented Nov 11, 2014 at 0:57
  • base dir? directory containing other directories (which in turn contain other directories)? yes, i've made an attempt, but wc won't work because it counts files. would ls work with a for loop in a bash script or is there something else I'm missing?
    – jml
    Commented Nov 11, 2014 at 1:03
  • What about symlinks to a directory? Commented Nov 11, 2014 at 1:09

6 Answers 6

19

This will find the number of non-hidden directories in the current working directory:

ls -l | grep "^d" | wc -l

EDIT:

To make this recursive, use the -R option to ls -l:

ls -lR | grep "^d" | wc -l
6
  • Thanks. I need this to be recursive; is there a modification that would comply? EDIT: this doesn't seem to omit hidden dirs
    – jml
    Commented Nov 11, 2014 at 1:48
  • If it is not omitting hidden directories, do you have an alias set for ls that is listing hidden directories by default? Commented Nov 11, 2014 at 2:05
  • Good point. I had one in my bash_profile. Thanks for the recursion update as well.
    – jml
    Commented Nov 11, 2014 at 2:10
  • Be cautious with the -R flag for ls. Check the output without the wc -l pipe, because I think ls -lR adds blank lines and dir names between files, which might throw off your count. Commented Nov 11, 2014 at 18:36
  • 3
    @transistor1 Good point. In this case however the grep "^d" displays only the entries which have a d at the beginning of the line. Blank/non-directory lines should not be displayed without the wc -l or counted with the wc -l. Commented Nov 11, 2014 at 18:47
6

In the GNU land:

find . -mindepth 1 -maxdepth 1 -type d -printf . | wc -c

elsewhere

find . -type d ! -name . -printf . -prune | wc -c

In bash:

shopt -s dotglob
count=0
for dir in *; do
  test -d "$dir" || continue
  test . = "$dir" && continue
  test .. = "$dir" && continue
  ((count++))
done
echo $count
1
  • -printf is GNU specific, while -mindepth/-maxdepth are now found in a few other implementations. Commented Oct 31, 2018 at 20:40
2

echo $(($(find -type d | wc -l) - 1)) is one way (subtract 1 from the wc -l to remove the current dir). You can tweak the options to find to find different things.

echo $(($(find -type d -not -path '*/\.*' | wc -l) - 1)) - to exclude the hidden dirs

As I mentioned in the comments, the heart of this expression is really find -type d, which finds all directories.

Note this finds all subfolders as well - you can control the depth using the -maxdepth flag.

2
  • that's interesting - so, there's no built in command to do something like this?
    – jml
    Commented Nov 11, 2014 at 1:16
  • 1
    @jml - Someone else likely has something simpler, but find is my go-to for file finding & counting. The "meat" of this ugly expression is really just find -type d, which finds any directories. Commented Nov 11, 2014 at 1:22
1

Did you try tree command?

tree -d /path/to/maindir| awk END{print}
1

In zsh:

(){echo $#} *(N/)

Recursively:

(){echo $#} **/*(N/)

Add the D glob qualifiers if you also want to count hidden directories.

POSIX equivalents:

ls -p | grep -c /

(add the -A option to ls for hidden ones)

Recursively:

LC_ALL=C find .//. ! -name . \( -name '.*' -prune -o -type d -print \) |
  grep -c //

Or

LC_ALL=C ls -Rqn . | grep -c '^d'

To include hidden ones:

LC_ALL=C find .//. ! -name . -type d | grep -c //

or:

LC_ALL=C ls -ARqn . | grep -c '^d'
0

find . -type d -not -path '.' -printf 0 | wc -c ;

Recursively find all directories (-type d) within current directory (find .) that is not (.) directory and print 0 for each directory found. Then wc -c counts the number of characters (0) from the previous command output.

1

You must log in to answer this question.

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