【发布时间】:2020-01-20 06:49:44
【问题描述】:
我有一个文件夹,其中包含大约 300k 个文件,每个文件包含 2-3mb 现在我想运行一个命令来查找 char { 在 shell 中的计数
我的命令:
nohup cat *20200119*| grep "{" | wc -l > /mpt_sftp/mpt_cdr_ocs/file.txt
这适用于少量文件 当我在拥有所有文件(300k 文件)的文件位置运行时,它会显示
参数太长
【问题讨论】:
我有一个文件夹,其中包含大约 300k 个文件,每个文件包含 2-3mb 现在我想运行一个命令来查找 char { 在 shell 中的计数
我的命令:
nohup cat *20200119*| grep "{" | wc -l > /mpt_sftp/mpt_cdr_ocs/file.txt
这适用于少量文件 当我在拥有所有文件(300k 文件)的文件位置运行时,它会显示
参数太长
【问题讨论】:
请您尝试以下方法:
find . -maxdepth 1 -type f -name "*20200119*" -print0 | xargs -0 grep -F -o "{" | wc -l > /mpt_sftp/mpt_cdr_ocs/file.txt
我实际测试了 300,000 个 10 个字符长的文件名,并且运行良好。
xargs 自动调整提供给grep 的参数列表的长度,我们无需担心。 (您可以通过将-t 选项置于xargs 来查看grep 命令的执行方式。)-F 选项大大加快了 grep 的执行速度,以搜索固定字符串,而不是正则表达式。{ 在一行中出现多次并且您想单独计算它们,则需要 -o 选项。【讨论】:
参数列表的最大大小各不相同,但通常为 128 KiB 或 256 KiB。这意味着如果*20200119* 部分溢出最大参数列表,您将拥有大量文件。但是您说“大约 30 万个文件”,即大约 300,000 个——每个文件中至少包含 8 个字符的日期字符串,加上足够的其他字符以使名称唯一,因此文件名列表将太长即使是最大的合理“最大参数列表大小”。
请注意,您的命令的nohup cat 部分是不明智的(请参阅UUoC: Useless Use of Cat);您应该使用grep '{' *20200119* 来节省不必要地通过管道传输所有数据。但是,这也会遇到参数列表过长的问题。
您可能必须使用以下命令的变体来获得所需的结果,而不会溢出您的命令行:
find . -depth 1 -name '*20200119*' -exec grep '{' {} + | wc -l
这使用了 POSIX find 的特性,它将尽可能多的参数组合到命令行中,而不会溢出以在大量(但不是太大)文件上运行 grep,然后传递grep 命令到 wc。如果您担心输出中出现的文件名,请使用 grep -h 隐藏它们。
或者你可以使用:
find . -depth 1 -name '*20200119*' -exec grep -c -h '{' {} + |
awk '{sum += $1} END {print sum}'
macOS 上的grep -c -h 在其参数列表中列出的每个文件的标准输出中生成一个简单数字(包含至少一个{ 的行数); GNU grep 也是如此。 awk 脚本将这些数字相加并打印结果。
在 macOS 上 find 支持使用 -depth 1; -maxdepth 1 也是如此——它们是等价的。 GNU find 似乎不支持 -depth 1。最好使用-maxdepth 1。 POSIX find 仅支持 -depth 没有编号。与使用 -depth 1 相比,使用 -maxdepth 1 和仅支持 POSIX 的最少选项集的 find 可能会得到更好的错误消息。
【讨论】: