是否有一个bash命令来计算匹配模式的文件数量?
例如,我想获取目录中所有文件的计数,这些文件都符合这个模式:log*
是否有一个bash命令来计算匹配模式的文件数量?
例如,我想获取目录中所有文件的计数,这些文件都符合这个模式:log*
当前回答
您可以使用-R选项来查找递归目录中的文件
ls -R | wc -l // to find all the files
ls -R | grep log | wc -l // to find the files which contains the word log
您可以在grep上使用模式
其他回答
这个问题的公认答案是错误的,但我有低代表,所以不能添加评论。
这个问题的正确答案由Mat给出:
shopt -s nullglob
logfiles=(*.log)
echo ${#logfiles[@]}
接受的答案的问题是wc -l计算换行符的数量,即使它们打印到终端,也将它们计算为'?'ls -l'的输出。这意味着当文件名包含换行符时,接受的答案失败。我已经测试了建议的命令:
ls -l log* | wc -l
而且即使只有一个文件名恰好包含换行符的文件与模式匹配,它也会错误地报告值2。例如:
touch log$'\n'def
ls log* -l | wc -l
要计算所有内容,只需将ls管道到单词计数行:
ls | wc -l
要使用模式计数,首先将管道连接到grep:
ls | grep log | wc -l
我已经对这个答案进行了很多思考,特别是考虑到不要解析这些东西。起初,我尝试过
<WARNING! DID NOT WORK>
du --inodes --files0-from=<(find . -maxdepth 1 -type f -print0) | awk '{sum+=int($1)}END{print sum}'
</WARNING! DID NOT WORK>
如果只有像这样的文件名,这是可行的
touch $'w\nlf.aa'
但如果我创建这样的文件名就失败了
touch $'firstline\n3 and some other\n1\n2\texciting\n86stuff.jpg'
我终于想到了下面这些。注意,我试图获得目录中所有文件的计数(不包括任何子目录)。我认为它,连同@Mat和@Dan_Yard的答案,以及至少有@mogsie设定的大部分要求(我不确定内存)。我认为@mogsie的答案是正确的,但我总是尽量避免解析ls,除非是非常特定的情况。
awk -F"\0" '{print NF-1}' < <(find . -maxdepth 1 -type f -print0) | awk '{sum+=$1}END{print sum}'
更可读的:
awk -F"\0" '{print NF-1}' < \
<(find . -maxdepth 1 -type f -print0) | \
awk '{sum+=$1}END{print sum}'
这是专门为文件执行查找,用空字符分隔输出(以避免空格和换行问题),然后计算空字符的数量。文件的数量将比空字符的数量少一个,因为在最后会有一个空字符。
要回答OP的问题,有两种情况需要考虑
1)非递归搜索:
awk -F"\0" '{print NF-1}' < \
<(find . -maxdepth 1 -type f -name "log*" -print0) | \
awk '{sum+=$1}END{print sum}'
2)递归搜索。请注意,name参数中的内容可能需要针对略有不同的行为(隐藏文件等)进行更改。
awk -F"\0" '{print NF-1}' < \
<(find . -type f -name "log*" -print0) | \
awk '{sum+=$1}END{print sum}'
如果有人想评论这些答案与我在这个答案中提到的答案相比如何,请评论。
注意,我是在得到这个答案的同时进行这个思考过程的。
这里有很多答案,但有些没有考虑在内
包含空格、换行符或控制字符的文件名 以连字符开头的文件名(想象一个名为-l的文件) 隐藏文件,以点开始(如果glob是*.log而不是log*) 匹配glob的目录(例如,一个名为logs的目录匹配log*) 空目录(即结果为0) 非常大的目录(列出所有目录会耗尽内存)
这里有一个解决方案可以处理所有这些问题:
ls 2>/dev/null -Ubad1 -- log* | wc -l
解释:
-U causes ls to not sort the entries, meaning it doesn't need to load the entire directory listing in memory -b prints C-style escapes for nongraphic characters, crucially causing newlines to be printed as \n. -a prints out all files, even hidden files (not strictly needed when the glob log* implies no hidden files) -d prints out directories without attempting to list the contents of the directory, which is what ls normally would do -1 makes sure that it's on one column (ls does this automatically when writing to a pipe, so it's not strictly necessary) 2>/dev/null redirects stderr so that if there are 0 log files, ignore the error message. (Note that shopt -s nullglob would cause ls to list the entire working directory instead.) wc -l consumes the directory listing as it's being generated, so the output of ls is never in memory at any point in time. -- File names are separated from the command using -- so as not to be understood as arguments to ls (in case log* is removed)
shell会将log*扩展到完整的文件列表,如果文件很多,可能会耗尽内存,所以通过grep运行会更好:
ls -Uba1 | grep ^log | wc -l
最后一种方法在不使用大量内存的情况下处理超大文件目录(尽管它使用了子shell)。不再需要-d,因为它只列出当前目录的内容。
这是我的一句话。
file_count=$( shopt -s nullglob ; set -- $directory_to_search_inside/* ; echo $#)