如何显示微调器直到命令行完成它的工作?换句话说,如果我正在运行一个脚本,并且我想在该脚本运行时显示微调器,并且当脚本完成时微调器会消失,这是工作。
下面是一个常见的微调器代码:
i=1
sp="/-\|"
echo -n ' '
while true
do
printf "\b${sp:i++%${#sp}:1}"
done
如何将以前的微调器代码链接到命令,以使其在命令运行时显示微调器,并在命令完成工作时微调器消失?如果我在循环中包含该命令,它将与微调器一起循环,那么这种情况下的解决方案是什么?
答案1
让你的while
循环监视你真正的退出命令。我假设 Linux 环境中每个 PID 都有 /proc 条目,但您可以通过其他方式对其进行切片:
#!/bin/bash
# your real command here, instead of sleep
sleep 7 &
PID=$!
i=1
sp="/-\|"
echo -n ' '
while [ -d /proc/$PID ]
do
printf "\b${sp:i++%${#sp}:1}"
done
答案2
这是另一个精美的旋转器,您可以像这样使用:
spinner ping google.com
echo "ping exited with exit code $?"
spinner sleep 10
echo "sleep exited with exit code $?"
# or, to check out the themes quickly
while spinner sleep 1; do echo; done
它有 12 个主题,并随机选择一个。
#!/bin/bash
# Shows a spinner while another command is running. Randomly picks one of 12 spinner styles.
# @args command to run (with any parameters) while showing a spinner.
# E.g. ‹spinner sleep 10›
function shutdown() {
tput cnorm # reset cursor
}
trap shutdown EXIT
function cursorBack() {
echo -en "\033[$1D"
# Mac compatible, but goes back to first column always. See comments
#echo -en "\r"
}
function spinner() {
# make sure we use non-unicode character type locale
# (that way it works for any locale as long as the font supports the characters)
local LC_CTYPE=C
local pid=$1 # Process Id of the previous running command
case $(($RANDOM % 12)) in
0)
local spin='⠁⠂⠄⡀⢀⠠⠐⠈'
local charwidth=3
;;
1)
local spin='-\|/'
local charwidth=1
;;
2)
local spin="▁▂▃▄▅▆▇█▇▆▅▄▃▂▁"
local charwidth=3
;;
3)
local spin="▉▊▋▌▍▎▏▎▍▌▋▊▉"
local charwidth=3
;;
4)
local spin='←↖↑↗→↘↓↙'
local charwidth=3
;;
5)
local spin='▖▘▝▗'
local charwidth=3
;;
6)
local spin='┤┘┴└├┌┬┐'
local charwidth=3
;;
7)
local spin='◢◣◤◥'
local charwidth=3
;;
8)
local spin='◰◳◲◱'
local charwidth=3
;;
9)
local spin='◴◷◶◵'
local charwidth=3
;;
10)
local spin='◐◓◑◒'
local charwidth=3
;;
11)
local spin='⣾⣽⣻⢿⡿⣟⣯⣷'
local charwidth=3
;;
esac
local i=0
tput civis # cursor invisible
while kill -0 $pid 2>/dev/null; do
local i=$(((i + $charwidth) % ${#spin}))
printf "%s" "${spin:$i:$charwidth}"
cursorBack 1
sleep .1
done
tput cnorm
wait $pid # capture exit code
return $?
}
("$@") &
spinner $!
答案3
这个 shell 脚本应该可以满足您的要求:
#!/usr/bin/env bash
show_spinner()
{
local -r pid="${1}"
local -r delay='0.75'
local spinstr='\|/-'
local temp
while ps a | awk '{print $1}' | grep -q "${pid}"; do
temp="${spinstr#?}"
printf " [%c] " "${spinstr}"
spinstr=${temp}${spinstr%"${temp}"}
sleep "${delay}"
printf "\b\b\b\b\b\b"
done
printf " \b\b\b\b"
}
("$@") &
show_spinner "$!"
假设您将 shell 脚本存储在名为 的文件中spinner
,则可以像这样调用它以在命令sleep 10
运行时显示微调器:
$ spinner sleep 10
答案4
有一些奇特的旋转器,我敢打赌每个答案都是正确的,尤其是@Jeff Schaller 的,但就我个人而言,作为一名开发人员,我喜欢能够阅读代码并确切地知道发生了什么。当我启动终端时,我想要一个 bash 脚本将所有 git 存储库复制到临时 zip 中,我还想要一个很酷的微调器来配合它,我不确定我的代码是否是最紧凑的,但它绝对有效很好,而且很简单易读。
我不是 bash 最了解的人,但我认为最大的问题是
- 在后台运行 while 循环(可能对 CPU 来说成本很高,但谁知道呢?)
- 我仍然可以移动光标,这很烦人
- 如果我想要多个过程发生,我不知道该怎么做
function runCommand() {
load & # calls the loading function
local whilePID=$! # gets the pid for the loop
tar -czf ${zipFileToUpdate} ${directoryToBackUp} & # backs up files
local backupPID=$! # get's back up pid
wait $backupPID # waits for backup id
kill $whilePID # kills the while loop
echo -ne "done" # echos done and removes the spinner
}
function load() { # just a function to hold the spinner loop, here you can put whatever
while true; do
echo -ne "/\r"
sleep .1
echo -ne "-\r"
sleep .1
echo -ne "\ \r"
sleep .1
echo -ne "|\r"
sleep .1
done
}
runCommand
^ 谈到我提到的关于多个命令的最后一个问题,我想我个人会将所有命令放在一个函数中,然后在后台运行该函数,但它们可能有一堆不同的 PID
经验:
function allCommands() {
command1;
command2;
command3;
...;
}
然后在runCommands()
函数中
function runCommand() {
load & # calls the loading function
local whilePID=$! # gets the pid for the loop
allCommands & # run function w/ all cmds
local allCmdPID=$!
...
}
该变量allCmdPID
可能与命令切换不同,您可能会等待第一个命令,然后终止加载循环,而其他命令仍在运行。可能的解决方法是:
- 在 for 循环中获取命令数组
- 获取命令的pid
- 等一下
- 然后继续执行下一个命令
但这一切看起来非常乏味。