有一个bash命令来统计文件吗?
有一个bash命令来计算匹配模式的文件数量吗?
例如,我想获得一个目录中与这种模式匹配的所有文件的计数: log*
这个简单的单行程应该在任何shell中工作,而不仅仅是bash:
ls -1q log* | wc -l
ls -1q会为每个文件提供一行,即使它们包含空格或特殊字符(如换行符)。
输出被输送到wc -l,它计算行数。
你可以安全地使用bash(即不会被空格或\n
的文件夹住)
$ shopt -s nullglob $ logfiles=(*.log) $ echo ${#logfiles[@]} $ shopt -u nullglob
您需要启用nullglob
以便在没有文件匹配的情况下,您不会在$logfiles
数组中获得文字*.log
。
尝试这个:
echo *.log | wc -w
或者为了recursionsearch:
find . -type f -name '*.log' | wc -l
wc -w
统计输出中的字数(bash将*.log
扩展为与该模式匹配的空格分隔的文件列表),而wc -l
将计算行数(每行打印一个结果)。
更新 :对于非recursionsearch,请执行以下操作:
find . -maxdepth 1 -type f -name '*.log' | wc -l
这将规避lanzz提到的空间问题。
这里有很多答案,但有些不考虑
- 包含空格,换行符或控制字符的文件名
- 以连字符开头的文件名(设想一个名为
-l
的文件) - 空目录(即结果为0)
- 非常大的目录(列出它们都可能会耗尽内存)
这是一个解决所有这些问题的解决scheme:
ls 2>/dev/null -Ub1 -- log* | wc -l
说明:
-
-U
导致ls
不对条目sorting,这意味着它不需要在内存中加载整个目录列表 -
-b
为非graphics字符打印C样式转义符,导致换行符被打印为\n
。 -
2>/dev/null
redirectstderr,以便如果有0个日志文件,则忽略错误消息。 (请注意,shopt -s nullglob
会导致ls
列出整个工作目录。) -
wc -l
在生成目录时会消耗目录列表,所以ls
的输出在任何时候都不会在内存中。 -
--
文件名与命令分开使用--
以便不被理解为ls
参数(如果删除了log*
)
shell 会将 log*
扩展到完整的文件列表,如果文件很多,可能会耗尽内存,那么通过grep运行它会更好:
ls -Ub1 | grep ^log | wc -l
这最后一个处理非常大的文件目录,而不使用大量的内存(尽pipe它使用子shell)。
这个问题接受的答案是错误的,但我有低代表所以不能添加评论。
这个问题的正确答案是由Mat给出的:
shopt -s nullglob logfiles=(*.log) echo ${#logfiles[@]}
被接受的答案的问题是wc -l计算换行符的数量,并且即使它们打印到terminal为'? 在'ls -l'的输出中。 这意味着当文件名包含换行符时,接受的答案FAILS。 我testing了build议的命令:
ls -l log* | wc -l
即使只有一个匹配名称恰好包含换行符的模式的文件,它也会错误地报告2的值。 例如:
touch log$'\n'def ls log* -l | wc -l
如果你有很多文件,并且你不想使用优雅的shopt -s nullglob
和bash数组解决scheme,只要不打印出文件名(可能包含换行符)。
find -maxdepth 1 -name "log*" -not -name ".*" -printf '%i\n' | wc -l
这将find所有匹配log *且不以.*
开始的文件.*
– “not name。*”是重复的,但重要的是要注意“ls”的默认值是不显示点文件,但是find的默认值是包含它们。
这是一个正确的答案,并且可以处理任何types的文件名,因为文件名永远不会在命令之间传递。
但是, shopt nullglob
答案是最好的答案!
这是我的一个class轮。
file_count=$( shopt -s nullglob ; set -- $directory_to_search_inside/* ; echo $#)
ls -1 log* | wc -l
这意味着每行列出一个文件,然后通过参数切换将其pipe理到字数统计命令来计算行数。