To find the number of names in a single directory, expand the *
glob in it and count the number of generated words:
shopt -s nullglob # to make the * glob expand to nothing
# if there is no matching names
set -- *
num=$#
printf '%s\n' "$num"
The special value $#
is the number of positional parameters. The set
command sets the positional parameters.
Would you want to count regular files only, and include hidden names, then use
shopt -s nullglob dotglob
for name in *; do
if [ ! -f "$name" ] || [ -L "$name" ]; then
# skip non-regular files and symbolic links
continue
fi
files+=( "$name" )
done
num=${#files[@]}
printf '%s\n' "$num"
To do that recursively into subdirectories, also set the globstar
shell option and use **/*
as the globbing pattern.
(in the zsh
shell, it would be enough with set -- **/*(.DN); print $#
)
The issue with your
num=$(( ls | wc -l ))
is twofold:
$(( ... ))
is an arithmetic expansion. You probably want a command substitution here, $( ... )
.
- The
wc -l
will not count files. It will count the number of newline characters outputted by ls
. A file with one or more newlines in its name will be counted as multiple files by wc -l
. You can test this by creating such a file using touch $'hello\nworld'
.