当在bash或*NIX中的任何其他shell中编写脚本时,在运行需要超过几秒钟时间的命令时,需要一个进度条。
例如,复制一个大文件,打开一个大tar文件。
你建议用什么方法向shell脚本添加进度条?
当在bash或*NIX中的任何其他shell中编写脚本时,在运行需要超过几秒钟时间的命令时,需要一个进度条。
例如,复制一个大文件,打开一个大tar文件。
你建议用什么方法向shell脚本添加进度条?
当前回答
许多答案描述了编写自己的命令来打印'\r' + $some_sort_of_progress_msg。有时问题是,每秒打印数百个这样的更新会减慢进程。
然而,如果你的任何进程产生输出(例如7z a -r newZipFile myFolder将输出每个文件名当它压缩它),那么一个更简单,快速,无痛和可定制的解决方案存在。
安装python模块tqdm。
$ sudo pip install tqdm
$ # now have fun
$ 7z a -r -bd newZipFile myFolder | tqdm >> /dev/null
$ # if we know the expected total, we can have a bar!
$ 7z a -r -bd newZipFile myFolder | grep -o Compressing | tqdm --total $(find myFolder -type f | wc -l) >> /dev/null
帮助:tqdm -h。使用更多选项的示例:
$ find / -name '*.py' -exec cat \{} \; | tqdm --unit loc --unit_scale True | wc -l
作为奖励,您还可以使用tqdm在python代码中包装可迭代对象。
https://github.com/tqdm/tqdm/blob/master/README.rst#module
其他回答
如果你必须显示一个临时进度条(通过提前知道显示时间),你可以像下面这样使用Python:
#!/bin/python
from time import sleep
import sys
if len(sys.argv) != 3:
print "Usage:", sys.argv[0], "<total_time>", "<progressbar_size>"
exit()
TOTTIME=float(sys.argv[1])
BARSIZE=float(sys.argv[2])
PERCRATE=100.0/TOTTIME
BARRATE=BARSIZE/TOTTIME
for i in range(int(TOTTIME)+1):
sys.stdout.write('\r')
s = "[%-"+str(int(BARSIZE))+"s] %d%% "
sys.stdout.write(s % ('='*int(BARRATE*i), int(PERCRATE*i)))
sys.stdout.flush()
SLEEPTIME = 1.0
if i == int(TOTTIME): SLEEPTIME = 0.1
sleep(SLEEPTIME)
print ""
然后,假设您将Python脚本保存为progressbar.py,可以通过运行以下命令从您的bash脚本中显示进度条:
python progressbar.py 10 50
它将显示一个50个字符大小的进度条,并“运行”10秒。
我需要一个进度条来迭代csv文件中的行。能够将cprn的代码改编成对我有用的东西:
BAR='##############################'
FILL='------------------------------'
totalLines=$(wc -l $file | awk '{print $1}') # num. lines in file
barLen=30
# --- iterate over lines in csv file ---
count=0
while IFS=, read -r _ col1 col2 col3; do
# update progress bar
count=$(($count + 1))
percent=$((($count * 100 / $totalLines * 100) / 100))
i=$(($percent * $barLen / 100))
echo -ne "\r[${BAR:0:$i}${FILL:$i:barLen}] $count/$totalLines ($percent%)"
# other stuff
(...)
done <$file
看起来是这样的:
[##----------------------------] 17128/218210 (7%)
首先将进程执行到后台,然后经常观察它的运行状态,即运行时打印模式并再次检查它的状态是否运行;
使用while循环频繁地监视进程的状态。
使用pgrep或任何其他命令来监视和获取进程的运行状态。
如果使用pgrep,则根据需要将不必要的输出重定向到/dev/null。
代码:
sleep 12&
while pgrep sleep &> /dev/null;do echo -en "#";sleep 0.5;done
此“#”将打印直到睡眠终止,此方法用于实现进度条的进度时间程序。
你也可以用这种方法来命令shell脚本,以可视化的方式分析它的进程时间。
错误: 这个pgrep方法在所有情况下都不起作用,出乎意料的是,另一个进程正在以相同的名称运行,while循环没有结束。
通过指定PID来获取进程的运行状态,使用 可能这个过程可以使用一些命令,
命令ps a将列出所有带有id的进程,您需要grep来查找指定进程的pid
要制作一个tar进度条
tar xzvf pippo.tgz |xargs -L 19 |xargs -I@ echo -n "."
其中“19”是tar中的文件数除以预期进度条的长度。 例如:.tgz包含140个文件,你想要一个76 "."的进度条,你可以放-L 2。
你什么都不需要了。
我想根据命令输出的行数和之前运行的目标行数来跟踪进度:
#!/bin/bash
function lines {
local file=$1
local default=$2
if [[ -f $file ]]; then
wc -l $file | awk '{print $1}';
else
echo $default
fi
}
function bar {
local items=$1
local total=$2
local size=$3
percent=$(($items*$size/$total % $size))
left=$(($size-$percent))
chars=$(local s=$(printf "%${percent}s"); echo "${s// /=}")
echo -ne "[$chars>";
printf "%${left}s"
echo -ne ']\r'
}
function clearbar {
local size=$1
printf " %${size}s "
echo -ne "\r"
}
function progress {
local pid=$1
local total=$2
local file=$3
bar 0 100 50
while [[ "$(ps a | awk '{print $1}' | grep $pid)" ]]; do
bar $(lines $file 0) $total 50
sleep 1
done
clearbar 50
wait $pid
return $?
}
然后这样使用它:
target=$(lines build.log 1000)
(mvn clean install > build.log 2>&1) &
progress $! $target build.log
它输出一个进度条,看起来像这样:
[===============================================> ]
条形图随着输出行数达到目标而增长。如果行数超过了目标,条就重新开始(希望目标是好的)。
BTW:我在Mac OSX上使用bash。我基于这个代码从mariascio旋转。