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.

When displaying directories using ls -l, their number of links (the second field in the output) is at least two: one for the dir name and one for .

$ mkdir foo
$ ls -l
total 2
drwxr-xr-x  2 user   wheel  512  4 oct 14:02 foo

Is it safe to always assume that the number of links above 2 corresponds to the number of subdirectories in this dir (.. links) ?

share|improve this question
add comment

5 Answers 5

up vote 7 down vote accepted

It is usually true on unix systems that the number of links to a directory is the number of subdirectories plus 2. However there are cases where this is not true:

  • Some unices allow hard links to directories. Then there will be more than 2 links that do not correspond to subdirectories.

  • There are filesystems where directories do not have entries for . and ... The GNU find manual mentions some examples in the discussion of its -noleaf option (which disables an optimization that assumes that . and .. exist in all directories): “CD-ROM or MS-DOS filesystems or AFS volume mount points”

An almost reliable way to count the number of subdirectories (it may still fail if a file name contains a newline character) is

$(($(LC_ALL=C ls -la /path/to/directory | grep '^d' | wc -l) - 2)

A more reliable way uses shell globs */ and .*/; as usual handling the case where the pattern doesn't match is a bit of a pain (except in bash and zsh where you can turn on the nullglob option).

share|improve this answer
add comment

ls -l |grep ^d|wc -l

share|improve this answer
add comment

I can't find anything in the documentation that confirms that the number of links will always be +2 on the number of subdirectories.

But, to find the correct ammount, use:

find . -type d -mindepth 1  -maxdepth 1 | wc -l

Or if you have to use ls -l, see the other answer.

share|improve this answer
    
I think you meant -type d, but: 1. this requires GNU find; 2. you need to subtract 1 for the starting directory (or pass -mindepth 1). –  Gilles Oct 4 '10 at 20:11
add comment

Don't use ls for this. Here's one way which works with all filenames, even those containing newlines, because it prints only a newline character instead of the filename:

find . -mindepth 1 -maxdepth 1 -type d -printf '\n' | wc -l

Edit: The current version doesn't result in any warnings, because -mindepth and -maxdepth should be before -type (the directory tree is pruned before checking for directories, to save time).

share|improve this answer
add comment

Here's yet another way to count subdirectories (non-recursively) in Bash:

(
shopt -s nullglob dotglob
printf '%s\000' */ | tr -dc '\0' | wc -c  # wc counts null bytes
)

Because each file name is being terminated by an ASCII NUL character, this should work correctly even if a file name contains a newline character.

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.