I found this code here https://www.tldp.org/HOWTO/Bash-Prompt-HOWTO/x700.html which nicely gives me the number of files in my directory.
ls -1 | wc -l
but I only want to know how many of those files' names start with 2009 (for example 20091210_005037.nc
).
I tried ls -1 | wc -l 2009*
but that slowly lists all the files and does not seem to give me a number.
Best Answer
This sets the list of positional parameters (
$1
,$2
, ..., etc.) to the names matching2009*
. The length of this list is$#
.The issue with
ls -1 | wc -l 2009*
is that you executewc -l
directly on the files matching2009*
, counting the number of lines in each. Meanwhile,ls -1
is trying to write to the standard input ofwc
, whichwc
is not reading from since it was given an explicit list of files to work on.You may have wanted to use
ls -d 2009* | wc -l
. This would have listed all the names that match2009*
(usingls
with-d
to not list the contents of directories), and would count the number of lines in the output. Note that-1
is not needed if you pipe the result ofls
somewhere (unlessls
is an alias or shell function that forces column output).Note also that this would give you the wrong count if any filename contains a newline:
However:
(using
set
and outputting$#
additionally does not use any external commands in most shells)Using
find
to count recursively:Here, we output a dot for each found pathname in or under the current directory, and then we count the number of lines that this produces. We don't count the filename strings themselves, and instead do it this way to avoid counting too many lines if a filename contains newlines.
With
find
we're able to more closely control the type of file that we count. Above, we explicitly test for regular files with-type f
(i.e. not directories and other types of files). The*
pattern in the shell does not distinguish between directories and files, but thezsh
shell can use*(.)
to modify the behaviour of the pattern to only match regular files (thezsh
user would probably use2009*(.)
instead of2009*
in the non-find
variations above and below).Using
**
in (withshopt -s globstar
inbash
, orset -o extended-glob
inyash
, or in any other shell that may support it), to count recursively:The pattern
**
matches almost like*
, but also matches across/
in pathnames.