2012-03-09 10 views
2

私の意図は、再帰的なログwgetを 'status bar'のように1行に出力することです。だから私は(私のwget呼び出しは少しより多くのオプションを持っているが、私は説明した問題のためにのみ不可欠なもの左)このパイプラインを組み立て:複雑なbashパイプラインがジャンプで動作する

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

は私がやって何を意味するのか説明しましょう。多分私の命令には何か問題があります。

  • は「再帰的ダウンロード」を意味します。
  • -nvは、それぞれのダウンロードに関するメッセージを「time:URL - > local file」のように簡潔にします。
  • stderrをstdoutにリダイレクトするので、パイプでメッセージを処理できます。
  • | cut -c1-80は、出力行を80文字にカットします。時には、URLとローカルファイル名が一緒になって長い文字列を作成し、行を2つ以上に分割します。そして私はそれをコンソールの1行に収める必要があります。 80は単なる例である。私のスクリプトでは、コンソールの幅をtput colsと決めています。
  • | xargs -I line echo -ne 'line\033[0K\r'は、前のコマンドの出力を表示し、次の2つの特殊文字を追加します。\033[OK - 行末。prevoiusの出力から残りの文字があれば残りの行を消去します。 \r - 現在の行の先頭にカーソルを設定するキャリッジリターン。

だから、希望の動作は次のとおりです。

  1. wgetは、ファイルをダウンロードし、すぐに
  2. cut stdoutにこのことについての通知を印刷しようとするwgetコマンドの出力をインターセプトし、80個の文字にそれをトリミング
  3. xargsトリミングされた行をキャッチしてそれを印刷しますすぐにと特殊文字

現在のダウンロードが表示されるステータスバーが表示されます。

しかし!私が見ていることは10秒から60秒間は何も起こらず、その間に行われたダウンロードに関するすべてのメッセージは約1秒で印刷されます。彼らは実際に私が望むように、しかし非常に速く印刷しました。次に、ポーズ、1秒間のメッセージの別の部分、など。だから、すぐに -nessを除いてすべてが問題ありません。

xargs部分を削除すると、メッセージはすぐに表示されます(ただし、1行では表示されません)。私がcut呼び出しを取り除くと、それらは瞬間ですが、実際には長いURLで改行されることがあります。 echoから特殊文字のみを取り除いても、出力は "跳ね上がり"、1行ではありません。

これを再現するには、「ftp://example.com」を再帰的なダウンロードのテストに使用できる任意のURL(HTTPも同様)に置き換えることができます。つまり、FTPに多数のファイルとディレクトリがあり、 HTTPの場合は、より多くのリンクを持つページへのリンクがたくさんあります(すべてのインターネットをダウンロードしようとする恐れはありません)。-rオプションのデフォルトの再帰レベルは5です。これを再現できない場合は、配布に問題があると思われますので、下記のコメント欄に記入してください。

P.S. wgetのステータスバーを整理するためのより良い方法が分かっているなら、あなたのコメントは大歓迎です。しかし、私はBashを学んでいて、何がこのような奇妙な行動を引き起こしているのか知りたいと思っています。たぶん、パイプやechoまたはxargsについてわかりません。ですから、このパイプラインは私が期待した通りに動作するのではないかという疑問があります。

答えて

1

問題は、出力バッファリングされ、このためのソリューションがあります:私はそれらを適用しようとするとTurn off buffering in pipe

は残念ながら、私はxargs: unmatched double quote; by default quotes are special to xargs unless you use the -0 optionを取得します。

あなたは異なるアプローチを試してみて、私は

+0

ありがとう!今私は問題(バッファリング)とそれをバイパスする方法(awk)の原因を知っています。そして確かに、xargsは文字列の操作にはあまり適していません。 – Hnatt

+1

その結果、私のパイプラインは次のようになりました: 'wget -r -nv http://example.com 2>&1 | awk -Wインタラクティブ '{ORS = ""; print substr($ 0,1,80) "\ 033 [0K \ r"} ''。 '-W interactive'はawksに出力をバッファしないようにし、' ORS = "" 'は改行なしで' print'を与えます。 – Hnatt

2

xargsは多くの行の入力を集め、コマンド(あなたの状況ではエコー)を1回だけ呼び出します。 xargsの引数に '-L 1'を加えて、これが役立つかどうか確認してください。

* xargsは、コマンドラインが長くなり過ぎる可能性がある場合は、コマンドの呼び出し回数を増やします。

+0

... awkは、PerlやPython、ルビーを試し、xargsはこの作業のために良い選択だとは思わない合理的なようだと私はそれについては知りませんでしたxargs、しかし:1)それは助けにはならない、あなたはそれを試して、それは働いたのですか? 2) '|パイプを切断すると、ラインを集めることなく期待どおりに動作します。 – Hnatt

+0

とにかく '-L'オプションについてのヒントをありがとう。私は '-I'でやや不調であることを知りました。それはマンページが言うことです。 – Hnatt

関連する問題