大きなディレクトリを同期するbashスクリプトがあり、--progress機能は優れていますが、これらすべての出力を1行に表示できますか?つまり。ファイルが転送されたときに画面をスクロールせずに進行状況を確認できるように、 --progress 出力を最後の行と同じ行に置きます。
答え1
ラッパースクリプト
以下はPTYをエミュレートし(rsyncが端末と同じように機能する必要があります)、Perlで書かれたラッパースクリプトドラフトです。 。次のようになります。
src/test.c
142 100% 0.19kB/s 0:00:00 (xfr#28, to-chk=0/30)
最初の行(ファイル名、src/test.c
)は、出力の現在のファイル名によって変わりますrsync
。 2番目の行は、rsync
更新されたステータス行が出力されるたびに変更されます。
気づく:私は1行ディスプレイの代わりに2行ディスプレイを選択しました(しかしそれでもスクロールしません!)。少なくとも一般的な使用法では、ステータス行と組み合わせると長いパス/ファイル名が表示されるためです。ただし、以下に示すように、ファイル/パス名とステータスを1行にまとめると簡単に変更できます。
終了すると、rsync
スクリプトは同じ終了コードで終了します(それでもエラーなどをキャッチできます)。
基本的な
OPとの議論によると、rsync
組み込みオプションが不足しrsync
ており、バージョンが古く、要件が一意です。だから私はカスタムスクリプトが目標を達成する唯一の方法だと思います。
他のオプションは、同様の出力をサポートするユーティリティがわからない場合でも、多くの「バックアップ」ラッパーユーティリティのrsync
1つを使用することです。
ソースコード
#!/usr/bin/env perl
# Custom progress wrapper for rsync
use 5.012;
use strict;
use warnings;
use autodie;
use IPC::Run qw/run start pump finish harness/;
my $RSYNC=`which rsync`; # Try to get rsync location from PATH
chomp $RSYNC;
my ($in,$out); # Input and output buffers
my $h = harness [ $RSYNC, @ARGV ], '<pty<', \$in, '>pty>', \$out;
local $| = 1; # Autoflush output
print "\n\n\e[2A\e[s"; # Make room and save cursor position
my ($file, $status) = ('',''); # Will hold filename and status lines
while ($h->pump) { parse() }
parse(); # Don't miss leftover output
$h->finish;
exit $h->result; # Pass through the exit code from rsync
# Parse and display file/status lines from rsync output
sub parse {
for (split /[\n\r]+/, $out) {
$file = $_ if /^\S/;
$status = $_ if /^\s/;
print "\e[u\e[0J$file\n$status\n";
}
$out = ''; # Clear output for next pump
}
前提条件
このスクリプトには2つの非標準モジュールIPC::Run
、およびが必要ですIO::Pty
。どちらもcpan
Perlに付属のプログラムを介してインストールできます。私を含む多くの人は、cpanm
次の行を使用してインストールすることを好みます。
curl -L https://cpanmin.us | perl - App::cpanminus
次に、次を実行します。
cpanm IPC::Run IO::Pty
サポートされる端末タイプ
これは実際に動作しますどのシンプルなANSIカーソル移動とコードクリアを使用して画面下部の数行を継続的に覆うため、最新の端末です。
使用法
私も同じだrsync
。直接指定する必要が--progress
ありますが、次の行を変更していくつかのデフォルトパラメータを簡単に編集できます$h = harness ...
。
my $h = harness [ $RSYNC, '--progress', @ARGV ], '<pty<', \$in, '>pty>', \$out;
rsync
バイナリ位置
rsync
which
スクリプトは、ほぼすべての環境で動作するバイナリの場所を自動的に決定しようとします。my $RSYNC='...'
必要に応じてこの行を編集してカスタムの場所を指定することもできます。(重要:この場合は、バックティック(`)を一重引用符(')に変更してください。 )
トラブルシューティング/拡張
エラー出力は特に処理されませんが、スクリプトを少し修正して処理できます。
かなり強力ですが、これは明らかに「高速」ですが、この非常に複雑なrsync
ユーティリティのすべての可能な出力を説明することはできません。必要に応じて少し調整する必要があります。とても簡単だと思います。すべての出力は変数に入り、$out
必要に応じて処理できます。
2ラインディスプレイから1ラインディスプレイに切り替える
上でも言ったように、私は2行を選びました。非スクロール長いパス名をよりよく収容するために表示されます。しかし、出力を単線ディスプレイに変換するのは簡単です。print ...
サブ行をparse()
次のように変更するだけです。
printf "\e[u\e[0J%-30.30s %s\n", $file, $status;
または、ANSIモーションコードを完全に取り除くには、次の手順を実行します。
printf "\r%-30.30s %-40.40s", $file, $status;
STDOUT->flush; # $| = 1 won't help you here
これにより、次の内容が表示されます。
src/test.c 142 100% 0.19kB/s 0:00:00 (xfr#28, to-chk=0/30)
%-30.30s
これがややランダムであることがわかります。印刷機能幅、あなたは正しいです。答えのようなものを採用することができます。この問題それに応じて、サイズを増減できるように端末の幅を取得します。
答え2
oneline
1行にスクロールしたいコンテンツをパイプする一般的なbashスクリプトがあります。
#!/bin/bash
cr=`tput cr;tput el`
if [ -z "$COLUMNS" ]
then COLUMNS=80
fi
while read line
do echo -n "$cr${line:0:$COLUMNS}"
done
echo
これはtput
キャリッジリターンを得ることです。行末まで消去したがって、短い行は長い行があった画面のジャンクを残しません。コマンドがstderrに出力される場合は、パイプする前にそれをstdoutにリダイレクトする必要があります。たとえばmycommand 2>&1 | oneline
。