2012-03-09 74 views
2

我的意图是在一行中输出递归日志wget,'status bar'-like。所以我组装这条管道(我wget调用有更多的选择,但我离开所述问题的唯一本质):复杂的bash管道跳转工作

wget -r -nv ftp://example.com 2>&1 | cut -c1-80 | xargs -I line echo -ne 'line\033[0K\r' 

让我解释一下我的意思做。也许我的命令有问题。

  • -r表示'递归下载';
  • -nv使有关每个下载的消息变得简短,如:“time:URL - > local file”;
  • stderr重定向到标准输出,所以我可以通过管道使用消息;
  • | cut -c1-80将输出行剪切为80个字符。有时URL和本地文件名一起构成一个长的字符串,将一行分成两行或更多。我需要它来适应单一行的控制台。例如,80站在这里。在我的脚本中,我用tput cols确定控制台宽度;输出前一命令的
  • | xargs -I line echo -ne 'line\033[0K\r'印刷品和增加了两个特殊字符:\033[OK - 线的端部,如果有从prevoius输出留下的任何字符,清洁线的其余部分;和\r - 回车,将光标设置为当前行的开头。

所以想要的行为是:

  1. wget下载文件,并试图打印这个通知,标准输出
  2. cut立即截获的wget的输出,并修剪到80个字符
  3. xargs捕捉修剪线并将其打印立即带特殊字符

所以我应该看到某种状态栏,其中显示当前下载。

但是!我看到的所有内容都没有发生10到60秒,然后在大约1秒内打印出有关在此期间完成的所有有关下载的消息。他们实际上以我想要的方式打印,但速度非常快。然后再次暂停,另一部分消息在1秒钟内,等等。所以一切都很好,除了立即-性。

当我删除xargs部分,消息被立即显示(但不是在一行中)。当我删除cut电话时,它们是即时的,但有时候这条线路会打破一些非常长的URL。如果我只从echo中删除特殊字符,输出仍然是“跳跃”而不是在一行中。

为了重现这一点,你可以用任何可以用于测试递归下载的URL(HTTP也可以)替换“ftp://example.com”,也就是说,在FTP有很多文件和目录的情况下HTTP的情况下有很多链接到有更多链接的页面(不要害怕它可能会尝试下载所有Internet,因为-r选项的默认递归级别为5)。如果你不能重现这一点,那么我认为这是我的发行版有问题,请在下面的评论部分写下它。

P.S.如果您知道更好的组织wget的状态栏的方式,您的意见非常受欢迎。但我正在学习Bash,并想知道是什么导致了这种奇怪的行为。也许有一些关于管道或echoxargs我不知道。所以问题是为什么这个管道工作得如此而且没有我预期的那样。

回答

1

问题是输出缓冲,也有解决方案了这一点:Turn off buffering in pipe

不幸的是,当我尝试应用它们,我得到xargs: unmatched double quote; by default quotes are special to xargs unless you use the -0 option

你必须尝试不同的方法,我不认为xargs是这个任务的一个很好的选择,尽量AWK,Perl,Python和红宝石......

+0

谢谢!现在我知道是什么导致了问题(缓冲)以及如何绕过它(awk)。是的,xargs真的不适合字符串操作。 – Hnatt 2012-03-09 13:36:43

+1

因此,我现在的流水线如下所示:'wget -r -nv http://example.com 2>&1 | awk -W interactive'{ORS =“”;打印substr($ 0,1,80)“\ 033 [0K \ r”}“'。 '-W interactive'使得awks不会缓冲输出,'ORS =“''给我们'print'没有换行符。 – Hnatt 2012-03-09 13:56:50

2

xargs收集许多行的输入并只调用一次命令(在你的情况下回声)*。将'-L 1'添加到xargs的参数并查看是否有帮助。

*如果命令行变得太长,xargs会使用更多的命令调用,但会尽可能多地进行分组。

+0

似乎是合理的,我不知道有关xargs,但是:1)它没有帮助,你是否尝试过,它的工作? 2)如果我删除'|切割“管道,它按预期工作,不会聚集线条。 – Hnatt 2012-03-09 12:39:19

+0

无论如何,感谢关于'-L'选项的提示。我了解到它与'-I'有一定的相容性。这就是人工页面所说的。 – Hnatt 2012-03-09 13:40:42