Fadi自己的解决方案很有帮助(并且由Adam Katz对相关答案的评论提供),但有两个警告:
\r,微调器仅在一行的开头工作.sleep只支持积分秒.在等待阻塞命令完成时,在哪里测试操作是否完成以及如何退出两个循环与如何使用微调器作为后台作业也可能不是很明显.
以下片段解决了这些问题; 他们使用\b(退格)而不是\r,如果需要,它允许微调器显示前面的文本:
异步案例(完成民意调查):
如果您正在等待异步完成一个进程(通过在循环中定期检查完成):
printf 'Processing: '
while :; do
for c in / - \\ \|; do # Loop over the sequence of spinner chars.
# Print next spinner char.
printf '%s\b' "$c"
# Perform your custom test to see if the operation is done here.
# In this example we wait for a file named 'results' to appear.
# Note that `[ -f results ] && ...` is just a shorter alternative to
# `if [ -f results]; then ... fi`.
[ -f results ] && { printf '\n'; break 2; } # Print a newline, break out of both loops.
sleep 1 # Sleep, then continue the loop.
done
done
Run Code Online (Sandbox Code Playgroud)
以上,由于印刷\b炭.在 spinner char.之后,将光标显示在微调器char 后面 ; 如果这在美学上是不合需要的,请使用以下变体将光标显示在微调器的顶部:
printf 'Processing: ' # note the extra space, which will be erased in the first iteration
while :; do
for c in / - \\ \|; do
printf '\b%s' "$c"
[ -f results ] && { printf '\n'; break 2; }
sleep 1
done
done
Run Code Online (Sandbox Code Playgroud)
I0_ol建议使用tput civis和tput cnorm到隐藏暂时光标 ; 同时严格符合POSIX标准的不(POSIX任务只有3个tput操作数:clear,init,和reset),但它似乎是由最先进的终端仿真器的支持.
printf 'Processing: '
tput civis # Hide cursor.
# To be safe, ensure that the cursor is turned back on when
# the script terminates, for whatever reason.
trap 'tput cnorm' EXIT
while :; do
for c in / - \\ \|; do
printf '%s\b' "$c"
[ -f results ] && { printf '\n'; break 2; }
sleep 1
done
done
tput cnorm # Show cursor again.
Run Code Online (Sandbox Code Playgroud)
一个更完整的例子与配置的超时和睡眠间隔(注意超时执法不准确的,因为它处理每个循环迭代没有考虑的时间;在bash,你可以简单地复位特殊变种SECONDS循环开始前然后检查它的值):
# Determine how long to sleep in each iteration
# and when to timeout (integral seconds).
sleepInterval=1 timeout=10 elapsed=0 timedOut=0
printf 'Processing: ' # note the extra space, which will be erased in the first iteration
while :; do
for c in / - \\ \|; do
printf '\b%s' "$c"
[ -f results ] && { printf '\nDone.\n'; break 2; }
[ $elapsed -ge $timeout ] && { timedOut=1; printf '\nTIMED OUT\n' >&2; break 2; }
sleep $sleepInterval
elapsed=$(( elapsed + sleepInterval ))
done
done
Run Code Online (Sandbox Code Playgroud)
同步(阻塞)案例:
如果您正在等待冗长的同步(阻塞)命令完成,则必须将微调器作为后台作业启动,然后在阻塞调用完成后终止该作业.
printf 'Processing: '
# Start the spinner in the background.
# The background job's PID is stored in special variable `$!`.
(while :; do for c in / - \\ \|; do printf '%s\b' "$c"; sleep 1; done; done) &
# Run the synchronous (blocking) command.
# In this example we simply sleep for a few seconds.
sleep 3
# The blocking command has finished:
# Print a newline and kill the spinner job.
{ printf '\n'; kill $! && wait $!; } 2>/dev/null
echo Done.
Run Code Online (Sandbox Code Playgroud)