Is there any method in Linux to calculate the number of files in a directory (that is, immediate children) in O(1) (independently of the number of files) without having to list the directory first? If not O(1), is there a reasonably efficient way?
I'm searching for an alternative to ls | wc -l
.
The
-U
option forls
is not in POSIX, and in OS X'sls
it has a different meaning from GNUls
, which is that it makes-t
and-l
use creation times instead of modification times.-f
is in POSIX as an XSI extension. The manual of GNUls
describes-f
asdo not sort, enable -aU, disable -ls --color
and-U
asdo not sort; list entries in directory order
.POSIX describes
-f
like this:Commands like
ls|wc -l
give the wrong result when filenames contain newlines.In zsh you can do something like this:
D
(glob_dots
) includes files whose name starts with a period andN
(null_glob
) causes the command to not result in an error in an empty directory.Or the same in bash:
If
IFS
contains ASCII digits, add double quotes around${#a[@]}
. Addshopt -u failglob
to ensure thatfailglob
is unset.A portable option is to use
find
:grep -c /
can be replaced withwc -l
if filenames do not contain newlines.! -name . -prune
is a portable alternative to-mindepth 1 -maxdepth 1
.Or here's another alternative that does not usually include files whose name starts with a period:
The command above does however include files whose name starts with a period when an option like
dotglob
in bash orglob_dots
in zsh is set. When*
matches no file, the command results in an error in zsh with the default settings.As far as I know, there is no better alternative. This information might be off-topic to this question and you may already know this that under Linux (in general under Unix) directories are just special file which contains the list of other files (I understand that the exact details will be dependent on specific file system but this is the general idea). And there is no call to find the total number of entries without traversing the whole list. Please make me correct if I'm wrong.