如何实时更新`wc -l`?

Foo*_*bar 19 shell-script wc

我有一个命令<streaming ls> | wc -l,它工作正常,但<streaming ls>需要一段时间,这意味着直到几分钟后我才能得到最终的行数。

wc -l有没有办法可以实时得到 update 的输出?

Ste*_*itt 33

您可以\xe2\x80\x99t 用于wc -l此目的,但您可以生成使用其他工具(例如 AWK)看到的行的运行计数:

\n
<streaming ls> | awk '{ printf "%d\\r", NR } END { print NR }'\n
Run Code Online (Sandbox Code Playgroud)\n

这将更新每次看到一行时看到的行数,并在进程结束时以总行数结束。

\n

对于产生大量输出的命令,可以通过每n行打印来减少开销:

\n
\xe2\x80\xa6 | awk 'NR % 10 == 0 { printf "%d\\r", NR } END { print NR }'\n
Run Code Online (Sandbox Code Playgroud)\n

(对于n = 10)或每秒打印一次:

\n
\xe2\x80\xa6 | awk 'systime() > lasttime { lasttime = systime(); printf "%d\\r", NR } END { print NR }'\n
Run Code Online (Sandbox Code Playgroud)\n

(或每n秒将条件更改为>= lasttime + n)。

\n

  • 如果您的输入有大量快速进入的行,您可以通过仅每 10 行更新一次计数(“NR % 10 == 0 { printf ...}”)来加快速度,并在以下位置打印确切的计数结束。更奇特的是,仅当自上次打印以来已经过了 100 毫秒时,才在一行进入时打印更新,也许在规则中使用 `if()`。但是+1,这是一个很好的简单起点,足以满足某些用例,例如生成行的命令有点慢,或者终端更新不是瓶颈。 (6认同)

Sté*_*las 25

您可以用来pv给您一些进度报告:

cmd | pv -lbtr | wc -l
Run Code Online (Sandbox Code Playgroud)
  • -l基于行(报告行数而不是字节数)。
  • -b报告字节数(这里有行,因为-l
  • -t报告所花费的时间
  • -r报告当前速率(每秒行数;另请参阅-a平均速率)。

请注意,文件名可以由多行组成,因此 的wc -l输出ls不能保证为您提供文件计数,除非您使用-b或 等选项-q将文件名中的换行符转义为\n?

  • @AustinHemmelgarn,不需要发生意外,如果您倾向于利用代码中错误地假设文件名不能包含换行符的错误,那么自愿创建这些文件是非常容易的。 (5认同)
  • 虽然您的最后警告在技术上是正确的,但这是一个非常小的边缘情况,因为普通人很难意外创建具有此类名称的文件,并且大多数人不需要多行文件名。编码时牢记此类情况很重要,但在交互使用 shell 时通常不值得担心。 (4认同)
  • @AustinHemmelgarn 并不难,我经常遇到这种情况。示例:我从网络上打开一个 PDF,想要将其保存在一个可识别的名称下,因此我只需复制 PDF 中的标题并将其粘贴到“另存为”对话框中。不幸的是,如果 PDF 中的标题分为多行,嵌入的换行符将被复制到文件名中。 (3认同)
  • `pv` 是一个非常强大的工具。 (2认同)