bashで経過秒数を表示するプログレスバーを実装したいと思います。このためには、画面に表示されている最後の行を消去する必要があります(コマンド「clear」はすべての画面を消去しますが、プログレスバーの行だけを消去して新しい情報に置き換える必要があります)。
最終結果は次のようになります。
$ Elapsed time 5 seconds
次に、10秒後に、この文(画面の同じ位置)を次のように置き換えます。
$ Elapsed time 15 seconds
キャリッジリターン自体は、カーソルを行の先頭に移動するだけです。出力の新しい各行が少なくとも前の行と同じ長さであれば問題ありませんが、新しい行が短い場合、前の行は完全に上書きされません。例:
$ echo -e "abcdefghijklmnopqrstuvwxyz\r0123456789"
0123456789klmnopqrstuvwxyz
新しいテキストの行を実際にクリアするには、 :\033[K
の後に追加します。\r
$ echo -e "abcdefghijklmnopqrstuvwxyz\r\033[K0123456789"
0123456789
\rでキャリッジリターンをエコーします
seq 1 1000000 | while read i; do echo -en "\r$i"; done
男エコーから:
-n do not output the trailing newline
-e enable interpretation of backslash escapes
\r carriage return
Derek Veitの答えは、線の長さが端子の幅を超えない限りうまく機能します。そうでない場合は、次のコードでジャンク出力を防止します。
行が初めて書き込まれる前に、
tput sc
これにより、現在のカーソル位置が保存されます。これで、行を印刷するときはいつでも、
tput rc
tput ed
echo "your stuff here"
最初に保存されたカーソル位置に戻り、次にカーソルから下に向かって画面をクリアし、最後に出力を書き込みます。
\033メソッドは私にはうまくいきませんでした。\ rメソッドは機能しますが、実際には何も消去せず、カーソルを行の先頭に置くだけです。したがって、新しい文字列が古い文字列よりも短い場合は、行の終わりに残りのテキストが表示されます。結局、tputが最善の方法でした。カーソル以外にも用途があり、多くのLinuxおよびBSDディストリビューションにプリインストールされているため、ほとんどのbashユーザーが利用できるはずです。
#/bin/bash
tput sc # save cursor
printf "Something that I made up for this string"
sleep 1
tput rc;tput el # rc = restore cursor, el = erase to end of line
printf "Another message for testing"
sleep 1
tput rc;tput el
printf "Yet another one"
sleep 1
tput rc;tput el
遊ぶための小さなカウントダウンスクリプトは次のとおりです。
#!/bin/bash
timeout () {
tput sc
time=$1; while [ $time -ge 0 ]; do
tput rc; tput el
printf "$2" $time
((time--))
sleep 1
done
tput rc; tput ed;
}
timeout 10 "Self-destructing in %s"
進行状況の出力が複数行の場合、またはスクリプトがすでに改行文字を出力している場合は、次のように行をジャンプできます。
printf "\033[5A"
これにより、カーソルが5行上にジャンプします。次に、必要なものを上書きできます。
それがうまくいかない場合は、printf "\e[5A"
またはecho -e "\033[5A"
を試すことができます。これは同じ効果があるはずです。
基本的に、エスケープシーケンスを使用すると、画面内のほとんどすべてを制御できます。
キャリッジリターン文字を使用します。
echo -e "Foo\rBar" # Will print "Bar"
キャリッジリターンを配置することで実現できます\r
。
1行のコードでprintf
for i in {10..1}; do printf "Counting down: $i\r" && sleep 1; done
またはとecho -ne
for i in {10..1}; do echo -ne "Counting down: $i\r" && sleep 1; done
前の行をクリアしたいだけの場合は、次の方法でうまくいく可能性があります。
printf '\033[1A\033[K'
複数行の場合は、ループで使用します。
for i in {1..10}; do
printf '\033[1A\033[K'
done
これにより、最後の10行がクリアされます。