shell脚本中的进度指示器

在脚本或者程序运行时间较长时,为终端用户提供反馈信息,表示脚本或程序在辛勤工作,是非常重要的。本文将介绍常见的两种进度指示器(一系列原点和一条旋转线)以及一些其他提供进度指示的工具。

1. 使用一系列原点来指示进度

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/bin/bash
function dots(){
seconds=${1:-5} # print a dot every 5 seconds by default
while true
do
     sleep $seconds
     echo -n '.'
done
}
 
dots 10 &
BG_PID=$!
trap "kill -9 $BG_PID" INT
 
# Do the real job here
sleep 150
kill $BG_PID
echo

dots函数每隔一段时间打印一个圆点,这个时间值可以通过第一个参数传入,否则默认为5秒。在后台启动dots函数之后,通过"$!"获取dots的pid,然后开始执行耗时的工作,在工作执行完毕之后kill掉后台执行的dots。trap命令是为了防止用户Ctrl_C中断脚本执行的时候dots仍然在后台执行。

2. 使用一条旋转线来表示进度

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#!/bin/bash
function rotate(){
INTERVAL=0.5
RCOUNT= "0"
echo -n 'Processing'
while :
do
     ((RCOUNT = RCOUNT + 1))
     case $RCOUNT in
         1) echo -e '-\b\c'
             sleep $INTERVAL
             ;;
         2) echo -e '\\\b\c'
             sleep $INTERVAL
             ;;
         3) echo -e '|\b\c'
             sleep $INTERVAL
             ;;
         4) echo -e '/\b\c'
             sleep $INTERVAL
             ;;
         *) RCOUNT=0
             ;;
     esac
done
}
rotate &
trap "kill -9 $BG_PID" INT
ROTATE_PID=$!
 
# Do the job here
sleep 15
kill -9 $ROTATE_PID
echo

为了使用一条旋转线来作为进度指示器,可以通过按顺序逐个显示/-\|然后重复这个过。为使这一字符序列无缝地显示,需要对前一个字符退格显示并删除它,或者用一个新字符来覆盖它,使得看起来好像一条线在旋转。

3、使用pv显示进度

pv(Pipe Viewer)可以显示通过管道的内容的数据通过量、数据通过速度、已用时间、估计剩余时间(ETA)、通过百分比等信息。在使用的时候,可以将pv插在两个进程的管道之间,并提供恰当的参数。比如为了查看tar备份的速度,可以用

?
1
tar czf - /path/to/some/directory/ *  | pv > backup. tar .gz

为了查看cp的速度,可以用

?
1
file = /path/to/some/file size=` ls -sk $ file | awk '{print $1}' ` && pv -s ${size}k $ file > /desination/filename

4. 使用dialog显示进度

dialog是一种在shell脚本里显示对话框的工具,其提供的--gauge可以用来作为进度条使用,其中进度大小从标准输入读入。下面是一个简单的例子:

?
1
for i in $( seq 0 10 100) ; do sleep 1; echo $i | dialog --gauge "Please wait" 10 70 0; done

下面的脚本提供对cp进度的显示

扫描二维码关注公众号,回复: 7260392 查看本文章
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/bin/bash
file =$1
newfile=$2
filename=` basename $ file `
if [ -d $newfile ]; then
     newfile=$newfile/$filename
fi
cp $ file $newfile &
CP_PID=$!
trap 'kill -9 $CP_PID' INT
size_old=`stat -c "%s" $ file `
size_new=`stat -c "%s" $newfile`
(
while [ $size_new -lt $size_old ];
do
     echo "$size_new * 100 / $size_old" | bc
     sleep 1
     size_new=`stat -c "%s" $newfile`
done
) | dialog --title "File Copy" --gauge "cp $file $newfile" 10 70 0

5. 另一种对cp提供进度显示的方法

这种方法来自这里 ,代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/bin/sh
cp_p()
{
    strace -q -ewrite cp -- "${1}" "${2}" 2>&1 \
       | awk '{
         count += $NF
             if (count % 10 == 0) {
                percent = count / total_size * 100
                printf "%3d%% [" , percent
                for (i=0;i<=percent;i++)
                   printf "="
                printf ">"
                for (i=percent;i<100;i++)
                   printf " "
                printf "]\r"
             }
          }
          END { print "" } ' total_size=$(stat -c ' %s' "${1}" ) count=0
}

在脚本或者程序运行时间较长时,为终端用户提供反馈信息,表示脚本或程序在辛勤工作,是非常重要的。本文将介绍常见的两种进度指示器(一系列原点和一条旋转线)以及一些其他提供进度指示的工具。

1. 使用一系列原点来指示进度

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/bin/bash
function dots(){
seconds=${1:-5} # print a dot every 5 seconds by default
while true
do
     sleep $seconds
     echo -n '.'
done
}
 
dots 10 &
BG_PID=$!
trap "kill -9 $BG_PID" INT
 
# Do the real job here
sleep 150
kill $BG_PID
echo

dots函数每隔一段时间打印一个圆点,这个时间值可以通过第一个参数传入,否则默认为5秒。在后台启动dots函数之后,通过"$!"获取dots的pid,然后开始执行耗时的工作,在工作执行完毕之后kill掉后台执行的dots。trap命令是为了防止用户Ctrl_C中断脚本执行的时候dots仍然在后台执行。

2. 使用一条旋转线来表示进度

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#!/bin/bash
function rotate(){
INTERVAL=0.5
RCOUNT= "0"
echo -n 'Processing'
while :
do
     ((RCOUNT = RCOUNT + 1))
     case $RCOUNT in
         1) echo -e '-\b\c'
             sleep $INTERVAL
             ;;
         2) echo -e '\\\b\c'
             sleep $INTERVAL
             ;;
         3) echo -e '|\b\c'
             sleep $INTERVAL
             ;;
         4) echo -e '/\b\c'
             sleep $INTERVAL
             ;;
         *) RCOUNT=0
             ;;
     esac
done
}
rotate &
trap "kill -9 $BG_PID" INT
ROTATE_PID=$!
 
# Do the job here
sleep 15
kill -9 $ROTATE_PID
echo

为了使用一条旋转线来作为进度指示器,可以通过按顺序逐个显示/-\|然后重复这个过。为使这一字符序列无缝地显示,需要对前一个字符退格显示并删除它,或者用一个新字符来覆盖它,使得看起来好像一条线在旋转。

3、使用pv显示进度

pv(Pipe Viewer)可以显示通过管道的内容的数据通过量、数据通过速度、已用时间、估计剩余时间(ETA)、通过百分比等信息。在使用的时候,可以将pv插在两个进程的管道之间,并提供恰当的参数。比如为了查看tar备份的速度,可以用

?
1
tar czf - /path/to/some/directory/ *  | pv > backup. tar .gz

为了查看cp的速度,可以用

?
1
file = /path/to/some/file size=` ls -sk $ file | awk '{print $1}' ` && pv -s ${size}k $ file > /desination/filename

4. 使用dialog显示进度

dialog是一种在shell脚本里显示对话框的工具,其提供的--gauge可以用来作为进度条使用,其中进度大小从标准输入读入。下面是一个简单的例子:

?
1
for i in $( seq 0 10 100) ; do sleep 1; echo $i | dialog --gauge "Please wait" 10 70 0; done

下面的脚本提供对cp进度的显示

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/bin/bash
file =$1
newfile=$2
filename=` basename $ file `
if [ -d $newfile ]; then
     newfile=$newfile/$filename
fi
cp $ file $newfile &
CP_PID=$!
trap 'kill -9 $CP_PID' INT
size_old=`stat -c "%s" $ file `
size_new=`stat -c "%s" $newfile`
(
while [ $size_new -lt $size_old ];
do
     echo "$size_new * 100 / $size_old" | bc
     sleep 1
     size_new=`stat -c "%s" $newfile`
done
) | dialog --title "File Copy" --gauge "cp $file $newfile" 10 70 0

5. 另一种对cp提供进度显示的方法

这种方法来自这里 ,代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/bin/sh
cp_p()
{
    strace -q -ewrite cp -- "${1}" "${2}" 2>&1 \
       | awk '{
         count += $NF
             if (count % 10 == 0) {
                percent = count / total_size * 100
                printf "%3d%% [" , percent
                for (i=0;i<=percent;i++)
                   printf "="
                printf ">"
                for (i=percent;i<100;i++)
                   printf " "
                printf "]\r"
             }
          }
          END { print "" } ' total_size=$(stat -c ' %s' "${1}" ) count=0
}

猜你喜欢

转载自www.cnblogs.com/zhangrui153169/p/11508123.html