【发布时间】:2012-03-26 21:13:05
【问题描述】:
我的意图是在一行中输出递归wget 的日志,类似于“状态栏”。所以我组装了这条管道(我的wget 电话有更多选择,但我只留下了对所描述的问题至关重要的那些):
wget -r -nv ftp://example.com 2>&1 | cut -c1-80 | xargs -I line echo -ne 'line\033[0K\r'
让我解释一下我的意思。也许我的命令有问题。
-
-r表示“递归下载”; -
-nv使有关每次下载的消息简短,例如:“时间:URL -> 本地文件”; -
&2>1将 stderr 重定向到 stdout,以便我可以通过管道处理消息; -
| cut -c1-80将输出行剪切为 80 个字符。有时 URL 和本地文件名一起构成一个长字符串,将一行分成 2 行或更多行。而且我需要它适合单行控制台。 80站在这里只是一个例子。在我的脚本中,我使用tput cols确定控制台宽度; -
| xargs -I line echo -ne 'line\033[0K\r'打印上一个命令的输出并添加两个特殊字符:\033[OK- 行尾,如果之前的输出中还有任何字符,它将清除行的其余部分;和\r- 回车,将光标设置到当前行的开头。
所以想要的行为是:
-
wget下载文件并尝试将有关此的通知打印到标准输出 -
cut立即截取 wget 的输出并将其修剪为 80 个字符 -
xargs捕捉到修剪过的线条并立即用特殊字符打印出来
所以我应该看到显示当前下载的某种状态栏。
但是! 我所看到的只是 10 到 60 秒内没有发生任何事情,然后在大约 1 秒内打印出所有关于在此期间完成的下载的消息。他们实际上以我想要的方式打印,但速度非常快。然后再一次,暂停,1 秒内的另一部分消息,依此类推。所以一切都很好,除了立即-ness。
当我删除xargs 部分时,消息会立即显示(但不是一行)。当我删除cut 调用时,它们是即时的,但有时会用一些非常长的 URL 换行。如果我从echo 调用中仅删除特殊字符,则输出仍然是“跳跃”而不是一行。
要重现这一点,您可以将“ftp://example.com”替换为可用于测试递归下载的任何 URL(HTTP 也可以),即如果 FTP 有许多文件和目录,并且以防万一HTTP 的许多链接指向具有更多链接的页面(不要担心它可能会尝试下载所有 Internet,因为 -r 选项的默认递归级别为 5)。如果你不能重现这个,那么我认为这是我的发行版有问题,请在下面的 cmets 部分写下它。
附:如果您知道为wget 组织状态栏的更好方法,非常欢迎您的 cmets。但我正在学习 Bash,想知道是什么导致了这种奇怪的行为。也许有一些关于管道或echo 或xargs 我不知道。所以问题是为什么这条管道如此有效,而不是像我预期的那样。
【问题讨论】:
标签: linux bash pipe statusbar xargs