【问题标题】:Use find, wc, and sed to count lines使用 find、wc 和 sed 计算行数
【发布时间】:2010-11-27 14:07:32
【问题描述】:

我试图使用 sed 来计算基于特定扩展名的所有行。

find -name '*.m' -exec wc -l {} \; | sed ...

我正在尝试执行以下操作,如何在此特定行中包含 sed 以获取总数。

【问题讨论】:

    标签: bash sed find wc


    【解决方案1】:

    在现代 GNU 平台上 wc 并找到 take -print0 和 -files0-from 参数,这些参数可以组合成一个命令,以计算文件中的行数并在末尾加上总数。示例:

    find . -name '*.c' -type f -print0 | wc -l --files0-from=-
    

    【讨论】:

      【解决方案2】:

      这里的大多数答案都不适用于大量文件。如果文件名列表对于单个命令行调用来说太长,有些会中断,有些会因为-exec 为每个文件启动一个新进程而效率低下。我相信一个强大而有效的解决方案是:

      find . -type f -name "*.m" -print0 | xargs -0 cat | wc -l
      

      以这种方式使用cat 很好,因为它的输出直接通过管道传输到wc,因此只有少量文件的内容一次保存在内存中。如果一次调用 cat 的文件太多,cat 将被多次调用,但所有输出仍将通过管道传输到单个 wc 进程中。

      【讨论】:

      • 或者改用标准/便携形式:find . -type f -name '*.m' -exec cat {} + | wc -l
      • 如何修改这个以打印出每个文件的总行数?
      【解决方案3】:

      对于大目录,我们应该使用:

      find . -type f -name '*.m' -exec sed -n '$=' '{}' + 2>/dev/null | awk '{ total+=$1 }END{print total}' 
      
      # alternative using awk twice
      find . -type f -name '*.m' -exec awk 'END {print NR}' '{}' + 2>/dev/null | awk '{ total+=$1 }END{print total}' 
      

      【讨论】:

        【解决方案4】:

        sed 不是正确的计数工具。改用 awk:

        find . -name '*.m' -exec awk '{print NR}' {} +
        

        使用 + 代替 \;强制 find 每找到 N 个文件就调用 awk(就像 xargs 一样)。

        【讨论】:

        • 搞笑,我其实是想说 awk
        【解决方案5】:

        嗯,如果您有很多文件,尤其是大文件,使用 cat 的解决方案可能会出现问题。

        第二个解决方案没有给出总数,只是每个文件的行数,正如我测试的那样。

        我更喜欢这样的:

        find . -name '*.m' | xargs wc -l | tail -1
        

        无论您拥有多少和多大的文件,这都能快速完成工作。

        【讨论】:

        • 如果单个命令行的文件太多,xargs 会将它们分块,这只会给出最终块的总数。
        【解决方案6】:

        您也可以使用 sed 代替 wc 来计算行数:

         find . -name '*.m' -exec sed -n '$=' {} \;
        

        '$=' 是一个保持行数的“特殊变量”

        编辑

        你也可以试试sloccount

        【讨论】:

        • 找到 . -name '*.m' -exec sed -n 'where $=' {} \;是这个吗?
        • 这不是总数,加在一起。
        • 好的,我结束了。 $查找。 -name '*.m' -exec sed -n '$=' {} \; |总和 - 22696 1
        • 其中 '$=' 是保持行数的“特殊变量”。你开玩笑的陛下! $= 代表一个地址和一个命令。 $ 是最后一行,命令= 是当前行号,与-n 开关一起抑制模式空间打印输出。结果是它计算输入给它的行数。
        • @dfa 谢谢。如何在计数前打印文件名?
        【解决方案7】:

        你也可以从 wc 获得漂亮的格式:

        wc `find -name '*.m'`
        

        【讨论】:

        • 添加-type f以避免目录名称匹配的情况:wc $(find -type f -name '*.m')
        • wc $(find -name '*.m') 更漂亮。
        • 这将破坏任何包含空格或其他 shell 元字符的文件名。
        【解决方案8】:

        您可以通过单个wc 实例cat 所有文件来获取总行数:

        find . -name '*.m' -exec cat {} \; | wc -l
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-05-24
          • 1970-01-01
          • 2012-11-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多