What's the best way to count the number of files in a directory?
Solution 1
How about this trick?
find . -maxdepth 1 -exec echo \; | wc -l
As portable as find
and wc
.
Solution 2
With bash, without external utilities, nor loops:
shopt -s dotglob
files=(*)
echo ${#files[@]}
In ksh, replace shopt -s dotglob
by FIGNORE=.?(.)
. In zsh, replace it by setopt glob_dots
, or remove the shopt
call and use files=(*(D))
. (Or just drop the line if you don't want to include dot files.) Portably, if you don't care about dot files:
set -- *
echo $#
If you do want to include dot files:
set -- *
if [ -e "$1" ]; then c=$#; else c=0; fi
set .[!.]*
if [ -e "$1" ]; then c=$((c+$#)); fi
set ..?*
if [ -e "$1" ]; then c=$((c+$#)); fi
echo $c
Solution 3
find . ! -name . -prune -print | grep -c /
Should be fairly portable to post-80s systems.
That counts all the directory entries except .
and ..
in the current directory.
To count files in subdirectories as well:
find .//. ! -name . | grep -c //
(that one should be portable even to Unix V6 (1975), since it doesn't need -prune
)
Solution 4
Try:
ls -b1A | wc -l
The -b
will have non-printable characters, -A
will show all files except .
and ..
and one per line (the default on a pipe, but good to be explicit).
As long as we're including higher-level scripting languages, here's a one-liner in Python:
python -c 'import os; print len(os.listdir(os.sep))'
Or with full 'find':
python -c 'import os; print len([j for i in os.walk(os.sep) for j in i[1]+i[2]])'
Solution 5
Have you considered perl, which should be relatively portable?
Something like:
use File::Find;
$counter = 0;
sub wanted {
-f && ++$counter
}
find(\&wanted, @directories_to_search);
print "$counter\n";
Related videos on Youtube
rahmu
Updated on September 18, 2022Comments
-
rahmu over 1 year
If parsing the output of
ls
is dangerous because it can break on some funky characters (spaces,\n
, ... ), what's the best way to know the number of files in a directory?I usualy rely on
find
to avoid this parsing, but similarly,find mydir | wc -l
will break for the same reasons.I'm working on Solaris right now, but I'm looking for a answer as portable across different unices and different shells as possible.
-
Admin over 9 yearsI'm not sure it's a duplicate, am I missing something?
-
Admin almost 9 yearsThis might be a duplicate, but not of the question indicated.
find
will get you number of files recursively (use-maxdepth 1
if you don't want that.find mydir -maxdepth 1 -type f -printf \\n | wc -l
should handle the special characters in the filename, as they are never printed in the first place.
-
-
Lekensteyn over 12 yearsTHis won't work for hidden files either unless the shell is configured to expand those with
*
. -
clerksx over 12 yearsThis doesn't work (it displays
n+1
files on my Debian system). It also doesn't filter for regular files. -
Nikhil Mulley over 12 years
gnu find . -maxdepth 1 -type f | wc -l
-
rahmu over 12 yearsI like this trick, very clever; but I'm surprised there's no simple straightforward way to do that!
-
enzotib over 12 years@Rush: this command should never raise "arg list too long". That only happens with external command (so never with
for
. -
Arcege over 12 years@ChrisDown the OP doesn't specify filtering for regular files, asks for number of files in a directory. To get rid of the n+1 issue, use
find . -maxdepth 1 ! -name . -exec echo \; | wc -l
; some older versions offind
do not have-not
. -
Stéphane Chazelas almost 9 yearsNote that
-maxdepth
is not standard (a GNU extension now also supported by a few other implementations). -
nisetama almost 8 yearsThe first example prints
1
for an empty directory whennullglob
is not enabled. In zsh,a=(*(DN));echo ${#a}
with theN
(nullglob
) qualifier does not result in an error for an empty directory. -
rahmu over 6 yearsYou might run into problems if the file name contains a
\n
or other funky chars (yeah, certain unices allow this). -
Josh Yang over 6 yearsI tried this explicitly before posting my answer and had no problems with it. I used nautilus file manager to rename a file to contain \n to try this.
-
Josh Yang over 6 yearsYou'r right it doesn't work like that. I don't know what I did when I tested this first. Tried again and updated my answer.
-
xhienne over 6 yearsNo, the command is OK, but there is already a similar solution and hidden files are not counted.
-
xhienne over 6 yearsOne of the rare portable answers on this page, if not the only one.
-
Anthony Geoghegan over 5 yearsI upvoted this answer yesterday as I found it also works well for directories other than the current directory (
find dirname ! -name dirname -prune -print
). I have since been wondering if there's any particular reason to usegrep -c /
instead ofwc -l
(which is probably more commonly used for counting). -
Stéphane Chazelas over 5 years
find dirname ! -name dirname
doesn't work if there are other directories within that are nameddirname
. It's better to usefind dirname/. ! -name .
.wc -l
counts the number of lines, file names can be made of several lines as the newline character is as valid as any in a file name.