使用 Bash 显示进度指示器
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12498304/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using Bash to display a progress indicator
提问by Pez Cuckow
Using a bash only script, how can you provide a bash progress indicator?
使用仅限 bash 的脚本,如何提供 bash 进度指示器?
So I can run a command form bash, and while that command is executing let the user know that something is still happening.
所以我可以从 bash 中运行一个命令,并且在执行该命令时让用户知道某些事情仍在发生。
回答by Pez Cuckow
In this example using SCP, I'm demonstrating how to grab the process id (pid) and then do something while that process is running.
在这个使用 SCP 的示例中,我将演示如何获取进程 ID (pid),然后在该进程运行时执行某些操作。
This displays a simple spinnng icon.
这将显示一个简单的旋转图标。
/usr/bin/scp [email protected]:file somewhere 2>/dev/null &
pid=$! # Process Id of the previous running command
spin[0]="-"
spin[1]="\"
spin[2]="|"
spin[3]="/"
echo -n "[copying] ${spin[0]}"
while [ kill -0 $pid ]
do
for i in "${spin[@]}"
do
echo -ne "\b$i"
sleep 0.1
done
done
William Pursell's solution
威廉珀塞尔的解决方案
/usr/bin/scp [email protected]:file somewhere 2>/dev/null &
pid=$! # Process Id of the previous running command
spin='-\|/'
i=0
while kill -0 $pid 2>/dev/null
do
i=$(( (i+1) %4 ))
printf "\r${spin:$i:1}"
sleep .1
done
回答by evil otto
If you have a way to estimate percentage done, such as the current number of files processed and total number, you can make a simple linear progress meter with a little math and assumptions about screen width.
如果您有一种方法可以估计完成的百分比,例如当前处理的文件数和总数,您可以制作一个简单的线性进度表,其中包含一些数学运算和有关屏幕宽度的假设。
count=0
total=34
pstr="[=======================================================================]"
while [ $count -lt $total ]; do
sleep 0.5 # this is work
count=$(( $count + 1 ))
pd=$(( $count * 73 / $total ))
printf "\r%3d.%1d%% %.${pd}s" $(( $count * 100 / $total )) $(( ($count * 1000 / $total) % 10 )) $pstr
done
Or instead of a linear meter you could estimate time remaining. It's about as accurate as other similar things.
或者,您可以估算剩余时间,而不是线性计。它与其他类似的东西一样准确。
count=0
total=34
start=`date +%s`
while [ $count -lt $total ]; do
sleep 0.5 # this is work
cur=`date +%s`
count=$(( $count + 1 ))
pd=$(( $count * 73 / $total ))
runtime=$(( $cur-$start ))
estremain=$(( ($runtime * $total / $count)-$runtime ))
printf "\r%d.%d%% complete ($count of $total) - est %d:%0.2d remaining\e[K" $(( $count*100/$total )) $(( ($count*1000/$total)%10)) $(( $estremain/60 )) $(( $estremain%60 ))
done
printf "\ndone\n"
回答by checksum
Referred from hereis a nice spinner function (with slight modification), will help your cursor to stay in original position also.
从这里引用的是一个很好的微调功能(稍作修改),也将帮助您的光标保持在原始位置。
spinner()
{
local pid=$!
local delay=0.75
local spinstr='|/-\'
while [ "$(ps a | awk '{print }' | grep $pid)" ]; do
local temp=${spinstr#?}
printf " [%c] " "$spinstr"
local spinstr=$temp${spinstr%"$temp"}
sleep $delay
printf "\b\b\b\b\b\b"
done
printf " \b\b\b\b"
}
with usage:
用法:
(a_long_running_task) &
spinner
回答by cosbor11
This is a pretty easy technique:
(just replace sleep 20
with whatever command you want to indicate is running)
这是一个非常简单的技术:(
只需替换sleep 20
为您想要指示正在运行的任何命令)
#!/bin/bash
sleep 20 & PID=$! #simulate a long process
echo "THIS MAY TAKE A WHILE, PLEASE BE PATIENT WHILE ______ IS RUNNING..."
printf "["
# While process is running...
while kill -0 $PID 2> /dev/null; do
printf "▓"
sleep 1
done
printf "] done!"
The output looks like this:
输出如下所示:
> THIS MAY TAKE A WHILE, PLEASE BE PATIENT WHILE ______ IS RUNNING...
> [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] done!
It adds a ▓
(high density dotted) every second until the process is complete.
它▓
每秒添加一个(高密度点),直到该过程完成。
回答by fipsbox
Here a simple onliner, that I use:
这是我使用的一个简单的在线工具:
while true; do for X in '-' '/' '|' '\'; do echo -en "\b$X"; sleep 0.1; done; done
回答by nachoparker
Aside from the classical spinner, you can use this progress bar
除了经典的微调器,您还可以使用此进度条
It achieves subcharacter precision by using half block characters
Code included on the link.
链接中包含的代码。
回答by f1lt3r
Here's my attempt. I'm new to bash scripts so some of this code may be terrible :)
这是我的尝试。我是 bash 脚本的新手,所以这些代码中的一些可能很糟糕:)
Example Output:
示例输出:
The Code:
编码:
progressBarWidth=20
# Function to draw progress bar
progressBar () {
# Calculate number of fill/empty slots in the bar
progress=$(echo "$progressBarWidth/$taskCount*$tasksDone" | bc -l)
fill=$(printf "%.0f\n" $progress)
if [ $fill -gt $progressBarWidth ]; then
fill=$progressBarWidth
fi
empty=$(($fill-$progressBarWidth))
# Percentage Calculation
percent=$(echo "100/$taskCount*$tasksDone" | bc -l)
percent=$(printf "%0.2f\n" $percent)
if [ $(echo "$percent>100" | bc) -gt 0 ]; then
percent="100.00"
fi
# Output to screen
printf "\r["
printf "%${fill}s" '' | tr ' ' ▉
printf "%${empty}s" '' | tr ' ' ?
printf "] $percent%% - $text "
}
## Collect task count
taskCount=33
tasksDone=0
while [ $tasksDone -le $taskCount ]; do
# Do your task
(( tasksDone += 1 ))
# Add some friendly output
text=$(echo "somefile-$tasksDone.dat")
# Draw the progress bar
progressBar $taskCount $taskDone $text
sleep 0.01
done
echo
You can see the source here: https://gist.github.com/F1LT3R/fa7f102b08a514f2c535
你可以在这里看到源:https: //gist.github.com/F1LT3R/fa7f102b08a514f2c535
回答by Victoria Stuart
Here is an example of an 'activity indicator,' for an internet connection speed test via the linux 'speedtest-cli' command:
这是一个“活动指示器”示例,用于通过 linux 'speedtest-cli' 命令进行互联网连接速度测试:
printf '\n\tInternet speed test: '
# http://stackoverflow.com/questions/12498304/using-bash-to-display-a-progress-working-indicator
spin[0]="-"
spin[1]="\"
spin[2]="|"
spin[3]="/"
# http://stackoverflow.com/questions/20165057/executing-bash-loop-while-command-is-running
speedtest > .st.txt & ## & : continue running script
pid=$! ## PID of last command
# If this script is killed, kill 'speedtest':
trap "kill $pid 2> /dev/null" EXIT
# While 'speedtest' is running:
while kill -0 $pid 2> /dev/null; do
for i in "${spin[@]}"
do
echo -ne "\b$i"
sleep 0.1
done
done
# Disable the trap on a normal exit:
trap - EXIT
printf "\n\t "
grep Download: .st.txt
printf "\t "
grep Upload: .st.txt
echo ''
rm -f st.txt
Update - example:
更新 - 示例:
回答by Hello World
https://github.com/extensionsapp/progre.sh
https://github.com/extensionsapp/progre.sh
Create 82 percent progress: progreSh 82
创造 82% 的进步: progreSh 82
回答by jan
I extended the answer of checksumin his answerby displaying a variable info message after the spinner:
#!/usr/bin/env bash
function spinner() {
local info=""
local pid=$!
local delay=0.75
local spinstr='|/-\'
while kill -0 $pid 2> /dev/null; do
local temp=${spinstr#?}
printf " [%c] $info" "$spinstr"
local spinstr=$temp${spinstr%"$temp"}
sleep $delay
local reset="\b\b\b\b\b\b"
for ((i=1; i<=$(echo $info | wc -c); i++)); do
reset+="\b"
done
printf $reset
done
printf " \b\b\b\b"
}
# usage:
(a_long_running_task) &
spinner "performing long running task..."
I don't like that if the stdout output with a spinner is redirected to a file, less
shows ^H
for each backspace instead of avoiding them in a file output at all. Is that possible with an easy spinner like this one?
我不喜欢如果带有微调器的 stdout 输出重定向到一个文件,则为每个退格less
显示^H
而不是在文件输出中完全避免它们。像这样一个简单的旋转器可以实现吗?