Dan*_*iel 191
这个简单的单行程应该适用于任何shell,而不仅仅是bash:
ls -1q log* | wc -l
ls -1q将为每个文件提供一行,即使它们包含空格或特殊字符(如换行符).
输出通过管道输出到wc -l,它计算行数.
Mat*_*Mat 48
您可以\n使用bash 安全地执行此操作(即不会被带有空格或名称的文件窃听):
$ shopt -s nullglob
$ logfiles=(*.log)
$ echo ${#logfiles[@]}
您需要启用nullglob,这样你就不会得到文字*.log中$logfiles 数组,如果没有文件匹配.(有关如何安全地重置它的示例,请参见如何"撤消"'set -x'?
mog*_*sie 45
这里有很多答案,但有些人没有考虑到
-l)*.log不是log*logs,匹配的目录log*)这是一个处理所有这些问题的解决方案:
ls 2>/dev/null -Ubad1 -- log* | wc -l
说明:
-U导致ls不对条目进行排序,这意味着它不需要在内存中加载整个目录列表-b为非图形字符打印C风格的转义,至关重要的是打印换行符\n.-a打印出所有文件,甚至是隐藏文件(当glob log*表示没有隐藏文件时不严格需要)-d打印出目录而不试图列出目录的内容,这是ls通常会做的-1 确保它在一列上(ls在写入管道时会自动执行此操作,因此不一定非必要)2>/dev/null重定向stderr,以便如果有0个日志文件,请忽略该错误消息.(注意这shopt -s nullglob会导致ls列出整个工作目录.)wc -l在生成目录列表时会消耗它,因此输出ls在任何时间点都不会在内存中.--文件名与命令分开使用,--以免被理解为参数ls(如果log*删除)shell 将扩展log*到完整的文件列表,如果文件很多,可能会耗尽内存,因此通过grep运行它会更好:
ls -Uba1 | grep ^log | wc -l
最后一个处理非常大的文件目录而不使用大量内存(虽然它确实使用了子shell).将-d不再是必要的,因为它仅列出当前目录的内容.
Wil*_*den 39
试试这个:
find . -type f -name '*.log' -printf x | wc -c
或者对于递归搜索:
find . -maxdepth 1 -type f -name '*.log' -printf x | wc -c
wc -c计算输出中的单词数(bash将扩展find为与该模式匹配的以空格分隔的文件列表),同时-printf x计算行数(find每行打印一个结果).
更新:对于非递归搜索,请执行以下操作:
find . -type f -name '*.log' -printf x | wc -c
这将绕过lanzz提到的空间问题.
这个问题的接受答案是错误的,但我的代表性很低,所以无法添加评论.
Mat给出了这个问题的正确答案:
shopt -s nullglob
logfiles=(*.log)
echo ${#logfiles[@]}
接受的答案的问题是wc -l计算换行符的数量,即使它们以"?"打印到终端,也要对它们进行计数.在'ls -l'的输出中.这意味着当文件名包含换行符时,接受的答案FAILS.我测试了建议的命令:
ls -l log* | wc -l
即使只有一个文件与名称恰好包含换行符的模式匹配,它也会错误地报告值2.例如:
touch log$'\n'def
ls log* -l | wc -l
如果你有很多文件并且你不想使用优雅shopt -s nullglob和bash数组解决方案,只要不打印文件名(可能包含换行符),就可以使用find等.
find -maxdepth 1 -name "log*" -not -name ".*" -printf '%i\n' | wc -l
这将找到所有匹配log*但不以.*- 开头的文件- "not name.*"是redunant,但重要的是要注意"ls"的默认值是不显示点文件,但是默认for find是包含它们.
这是一个正确的答案,并处理您可以抛出的任何类型的文件名,因为文件名永远不会在命令之间传递.
但是,shopt nullglob答案是最好的答案!
这是我的衬里。
 file_count=$( shopt -s nullglob ; set -- $directory_to_search_inside/* ; echo $#)
(没有足够的声誉发表评论)
这是BUGGY:
ls -1q some_pattern | wc -l
如果shopt -s nullglob碰巧被设置,它会打印所有常规文件的数量,而不仅仅是具有模式的文件(在 CentOS-8 和 Cygwin 上测试)。谁知道还有哪些其他无意义的错误ls?
这是正确的,而且速度要快得多:
shopt -s nullglob; files=(some_pattern); echo ${#files[@]};
它完成了预期的工作。
0.006在 CentOS 和0.083Cygwin 上(以防它被小心使用)。
0.000在 CentOS 和0.003Cygwin 上。
        您可以使用 -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 上使用模式
您可以使用 shell 函数轻松定义这样的命令。此方法不需要任何外部程序,也不会生成任何子进程。它不会尝试危险的ls解析,并且可以很好地处理 \xe2\x80\x9cspecial\xe2\x80\x9d 字符(空格、换行符、反斜杠等)。它仅依赖于shell提供的文件名扩展机制。它至少与 sh、bash 和 zsh 兼容。
下面的行定义了一个名为的函数count,该函数打印调用该函数的参数数量。
count() { echo $#; }\n只需使用所需的模式调用它:
\n\ncount log*\n为了在通配模式不匹配时得到正确的结果,必须在扩展发生时设置shell 选项nullglob(或\xe2\x80\x94,这是 zsh 上的默认行为)。failglob可以这样设置:
shopt -s nullglob    # for sh / bash\nsetopt nullglob      # for zsh\n根据您想要计算的内容,您可能还对 shell 选项感兴趣dotglob。
不幸的是,至少对于 bash,在本地设置这些选项并不容易。如果您不想全局设置它们,最直接的解决方案是以这种更复杂的方式使用该函数:
\n\n( shopt -s nullglob ; shopt -u failglob ; count log* )\n如果你想恢复轻量级语法count log*,或者如果你真的想避免生成子 shell,你可以按照以下方式进行一些修改:
# sh / bash:\n# the alias is expanded before the globbing pattern, so we\n# can set required options before the globbing gets expanded,\n# and restore them afterwards.\ncount() {\n    eval "$_count_saved_shopts"\n    unset _count_saved_shopts\n    echo $#\n}\nalias count=\'\n    _count_saved_shopts="$(shopt -p nullglob failglob)"\n    shopt -s nullglob\n    shopt -u failglob\n    count\'\n作为奖励,此功能具有更普遍的用途。例如:
\n\ncount a* b*          # count files which match either a* or b*\ncount $(jobs -ps)    # count stopped jobs (sh / bash)\n通过将函数转换为可从 PATH 调用的脚本文件(或等效的 C 程序),它也可以由诸如find和 之类的程序组成xargs:
find "$FIND_OPTIONS" -exec count {} \\+    # count results of a search\n