2012-03-09 72 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