是否可以在一行上顯示 rsync 輸出?
我有一個 bash 腳本,它正在對一個大目錄進行 rsync,而且 –progress 功能很棒,但是是否可以在一行中顯示所有這些輸出?IE。當文件傳輸時,只需將 –progress 輸出吐到最後一行,這樣我就可以在不滾動螢幕的情況下觀看進度?
包裝腳本
這是一個用 Perl 編寫的包裝腳本的草稿,它將模擬 PTY(因此 rsync 的行為應該與在終端中的行為完全相同),並解析輸出,以便它可以保持執行的文件名和兩行顯示轉移狀態。它看起來像這樣:
src/test.c 142 100% 0.19kB/s 0:00:00 (xfr#28, to-chk=0/30)
第一行 (filename,
src/test.c
) 將根據 . 輸出的目前文件名而改變rsync
。rsync
每當輸出更新的狀態行時,第二行就會改變。**注意:**我選擇了 2 行顯示(但仍然不會滾動!)而不是 1 行顯示,至少在我的典型用法中,我最終會得到長路徑/文件名,當結合狀態行。但是,正如您將在下面看到的,將文件/路徑名和狀態合併到一行中會很容易進行修改。
rsync
退出時,腳本以相同的退出程式碼退出(因此您仍然可以擷取錯誤等)基本原理
根據與 OP 的討論,內置
rsync
選項不足,它們的版本rsync
較舊,並且它們的需求是獨特的。因此,我覺得自定義腳本是實現他們目標的唯一方法。其他選擇是使用
rsync
已經存在的許多現有“備份”包裝實用程序中的任何一種,儘管我不知道有任何支持類似輸出的實用程序。原始碼
#!/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 }
先決條件
該腳本需要兩個非標準模組:
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
變數,您可以根據需要對其進行處理。轉換為 1 行顯示而不是 2 行顯示
如上所述,我選擇了 2 行非滾動顯示以更好地適應長路徑名。但是,將輸出轉換為 1 行顯示是微不足道的。只需將sub 中的
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
是一個相當隨意的printf寬度,您是對的。您可以使用類似這個問題的答案來獲取終端寬度,以便您可以相應地增大/縮小該尺寸。