例如,我想计算当前目录中有多少文件具有特定扩展名。
我用了:
ls | grep ".txt" | wc -l
这有效,也有效:
ls | grep ".txt*" | wc -l
但为什么这也不起作用呢?
ls | grep "*.txt" | wc -l
为什么当我在扩展名之前使用通配符时,它在 grep 表达式中似乎不起作用?为什么它在最后没有效果(所有 txt 文件都以 .txt 结尾,所以我猜如果它是某种东西,它就不起作用像.txt.zip)?
答案1
$ ls *.txt
该命令将使用 shell 通配列出所有名称以.txt
.
$ ls | grep "*.txt"
此命令将列出当前工作目录中的所有(非隐藏)文件,并将该输出发送到grep
,这将根据正则表达式匹配文件名/*.txt/
。
/*.txt/
该正则表达式可能(取决于正在使用的正则表达式的风格)匹配以下模式:
* -- 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
在正则表达式中,*
是一个通配符,代表“零个或多个前面的子表达式”;但它的工作方式与 shell glob 通配符不同。相关地,.
不是句点;它是一个字符的通配符(类似于?
shell glob 中的通配符)。因此,这个表达式将(再次取决于正则表达式的风格)匹配file.txt
、sometxtfile
、中的任何一个photo_of_a_txt_file.png
,但实际上不匹配txtfile
(因为 之前的一个字符不匹配txt
)。因此,重要的是要知道,文字字符串txt
可以出现在除使用此正则表达式的文件名开头之外的任何位置。
捕获以以下结尾的文件名的更好的正则表达式.txt
是/\.txt$/
:
\. -- A literal .
txt -- The literal string 'txt'
$ -- End of input
因此,如果你坚持管道ls
进入grep
(暂时不要进入那些可以写为什么解析 的输出ls
是一个坏主意的书),你可能打算这样做:
$ ls | grep "\.txt$"
至于然后使用wc
,你不需要这样做。 grep
可以数:
$ ls | grep -c "\.txt$"