$ ls *.txt
This command will use shell globbing to list all files whose names end with .txt
.
$ ls | grep "*.txt"
This command will list all (non-hidden) files in the present working directory, and send that output to grep
, which will match the filenames against the regular expression /*.txt/
.
/*.txt/
This regular expression may (depending on what flavor of regular expressions is in play) match a pattern of:
* -- zero or more characters of any type (or possibly only a literal '*'), followed by
. -- exactly one character of any type, followed by
txt -- the literal string 'txt', followed by anything
In regular expressions, *
is a wildcard standing for "zero or more of the preceding subexpression"; but it works differently from shell glob wildcards. Relatedly, .
is not a period; it is a wildcard for one character (analogous to the ?
wildcard in shell globs). As such, this expression would (again, depending on what flavor of regex) match any of file.txt
, sometxtfile
, photo_of_a_txt_file.png
, but indeed not txtfile
(as there is no match for the one character before txt
). It is important to know that the literal string txt
can, therefore, appear anywhere but at the very start of the file name with this regular expression.
A better regular expression to catch file names that end in .txt
would be /\.txt$/
:
\. -- A literal .
txt -- The literal string 'txt'
$ -- End of input
So therefore, if you insist on piping ls
into grep
(and let's not, for the moment, get into the books that could be written on why parsing the output of ls
is a bad idea), you probably mean to do this:
$ ls | grep "\.txt$"
As for then using wc
, you don't need to do this. grep
can count:
$ ls | grep -c "\.txt$"
grep
uses regular expressions, not wildcards - see for example How do regular expressions differ from wildcards used to filter files – steeldriver Jan 08 '20 at 18:33ls
(and what to do instead)?, Why you shouldn't parse the output of ls(1) – phuclv Feb 27 '24 at 06:31