Use just ! -path .
. The pathnames that find
carries out its tests on are relative to the search path that you use, and the .
directory will show up as just .
to find
in your example command. Had you used any other search path, you would have used that in the test to avoid listing it (e.g. find "$HOME" ! -path "$HOME"
).
Note too that by using wc -l
, you are not actually counting files but the number of lines produced by find
, which may be more than the number of files if any name contains newlines.
With a POSIX find
, you could use
find . ! -path . -prune -exec echo x \; | wc -l
to count the number of names in the current directory. Here, -prune
would stop find
from entering any subdirectories and -exec echo x \;
would output an x
character on a line for each found name. These lines would then be counted by wc -l
.
As for not showing .
or ..
with ls
, use ls -A
instead of ls -a
.
Another way to count the names in a single directory, which allows for all possible filenames, would be
shopt -s dotglob nullglob
set -- *
echo "$#"
... in bash
, or
set -- *(DN)
echo $#
... in zsh
(where (DN)
modifies the behavior of *
so that it also matches hidden names and so that the pattern is completely removed if there are no matches, much like the effect of enabling the dotglob
and nullglob
shell options in bash
).
Both of these pieces of code sets the positional parameters to the list of names in the current directory, including hidden names. Once that has been done, the number of set positional parameters are found in the special variable $#
.
The *
globbing pattern does not match .
nor ..
. Not even when asked to match hidden names.
In the yash
shell, setting the dot-glob
shell option with set -o dot-glob
makes *
match hidden names, including both .
and ..
, so you may want to deduct 2 from the value of $#
if you're using this shell.