• Linux|shell编程|拷贝大文件之显示进度条


    前言:

    Linux由于自身并不是一个图形化的界面,因此,命令行是它的一个基础交互模式,而我们有的时候需要进度条来让程序运行的更加美观,更加直观,例如,一些比较消耗io的操作,文件拷贝,比如某个文件十几G甚至上百G,需要拷贝到本机的其它分区,那么,一个直观的进度条就十分有用了,可以让我们大致估算出多少时间拷贝完成,从而进行下一步的工作。

    那么,本文将以一个10G的文件拷贝为例,输出一个按实际拷贝进度来显示的进度条。

    一,

    测试文件的准备

    time命令统计dd命令的执行时间,可以看到用时1分钟6秒,硬盘速度161M每秒。

    我的硬盘速度还算可以的

    1. [root@centos61 ~]# time dd if=/dev/zero of=Demofile bs=100M count=100
    2. 100+0 records in
    3. 100+0 records out
    4. 10485760000 bytes (10 GB) copied, 65.3247 s, 161 MB/s
    5. real 1m5.869s
    6. user 0m0.001s
    7. sys 0m13.644s
    8. [root@centos61 ~]# ls -alh Demofile
    9. -rw-r--r--. 1 root root 9.8G May 27 17:41 Demofile

    二,

    带实际拷贝进度的进度条的shell脚本(本文暂定该脚本名称为copyfile.sh):

    1. #!/bin/bash
    2. SOURCE=$1
    3. TARGET=$2
    4. CP=cp
    5. $CP "$SOURCE" "$TARGET" &
    6. CPID=$!
    7. trap "onCtrlC" INT
    8. function onCtrlC () {
    9. #捕获CTRL+C,当脚本被ctrl+c的形式终止时同时终止程序的后台进程
    10. kill -9 ${isalive} ${CPID}
    11. echo
    12. echo 'Ctrl+C is captured,拷贝已停止'
    13. exit 1
    14. }
    15. isalive(){
    16. out=`ps -p $1 2> /dev/null`
    17. return $?
    18. }
    19. while 2>1; do
    20. { SSIZE=`/bin/ls -l $SOURCE | gawk "{print \\\$5}"`
    21. if [ -f $TARGET ]; then
    22. TSIZE=`/bin/ls -l $TARGET | gawk "{print \\\$5}"`
    23. else
    24. TSIZE="0"
    25. fi
    26. PERCENT=`echo "scale=2; $TSIZE/$SSIZE*100" | bc -l`
    27. RATE=`echo "scale=0; 63*$PERCENT/100" | bc -l`
    28. BLUE="\\033[3;44m"
    29. NORMAIL="\\033[0;39m"
    30. BAR=$BLUE
    31. i=0
    32. while [ $i -le 62 ]; do
    33. [ $i = $RATE ] && BAR=$BAR"\\033[7;39m"
    34. BAR=$BAR" "
    35. let i=$i+1
    36. done
    37. BAR=$BAR$NORMAIL
    38. echo -en "\r$BAR ${PERCENT}%"
    39. if ! isalive "$CPID"; then echo -en "\n"; exit; fi
    40. sleep 1
    41. }
    42. done

    脚本运行效果:

    1. [root@centos61 ~]# bash copyfile.sh Demofile Demofile-bak
    2. 14.00%^C
    3. Ctrl+C is captured,拷贝已停止

    此时到百分之14的时候按ctrl+c停止了,我们可以核对一下目标文件是否是源文件的百分之14:

    可以计算出1.5除以9.8确实是百分之14

    1. [root@centos61 ~]# ls -alh Demofile*
    2. -rw-r--r--. 1 root root 9.8G May 27 17:41 Demofile
    3. -rw-r--r--. 1 root root 1.5G May 27 18:25 Demofile-bak

     shell脚本完美运行!!!!!!

    完整运行:

    1. [root@centos61 ~]# time bash copyfile.sh Demofile Demofile-bak
    2. 100.00%
    3. real 2m6.804s
    4. user 0m1.769s
    5. sys 0m22.517s
    6. [root@centos61 ~]# ls -al Demofile*
    7. -rw-r--r--. 1 root root 10485760000 May 27 17:41 Demofile
    8. -rw-r--r--. 1 root root 10485760000 May 27 18:36 Demofile-bak

     

     

    三,

    脚本说明:

    • $1 代表源文件,本例是Demofile,$2 代表目标文件,本例是Demofile-bak
    • 实际的拷贝命令是在后台运行,因为前台需要显示的是进度条,因此是$CP "$SOURCE" "$TARGET" &

    trap "onCtrlC" INT
    function onCtrlC () {
            #捕获CTRL+C,当脚本被ctrl+c的形式终止时同时终止程序的后台进程
            kill -9 ${isalive} ${CPID}
            echo
            echo 'Ctrl+C is captured,拷贝已停止'
            exit 1
    }

     

    这一块是抓取中断信号,如果不想拷贝了的情况下,ctrl+c停止脚本,这样会使得脚本退出更为优雅。

    isalive(){
            out=`ps -p $1 2> /dev/null`
            return $?
    }

     

    这一块是监听拷贝程序的 pid,当返回值为1的时候,表示拷贝完成,程序停止退出。

    一个循环的debug如下:

    1. ++ ps -p 35785
    2. + out=' PID TTY TIME CMD
    3. 35785 pts/1 00:00:15 cp'
    4. + return 0
    5. + sleep 1
    6. ++ /bin/ls -l Demofile
    7. ++ gawk '{print $5}'
    8. + SSIZE=10485760000
    9. + '[' -f Demofile-bak ']'
    10. ++ /bin/ls -l Demofile-bak
    11. ++ gawk '{print $5}'
    12. + TSIZE=10337685504
    13. ++ echo 'scale=2; 10337685504/10485760000*100'
    14. ++ bc -l
    15. + PERCENT=98.00
    16. ++ echo 'scale=0; 63*98.00/100'
    17. ++ bc -l
    18. + RATE=61
    19. + BLUE='\033[3;44m'
    20. + NORMAIL='\033[0;39m'
    21. + BAR='\033[3;44m'
    22. + i=0
    23. + '[' 0 -le 62 ']'
    24. + '[' 0 = 61 ']'
    25. + BAR='\033[3;44m '
    26. + let i=0+1
    27. + '[' 1 -le 62 ']'
    28. + '[' 1 = 61 ']'
    29. + BAR='\033[3;44m '
    30. + let i=1+1
    31. + '[' 2 -le 62 ']'
    32. + '[' 2 = 61 ']'
    33. + BAR='\033[3;44m '
    34. + let i=2+1
    35. + '[' 3 -le 62 ']'
    36. + '[' 3 = 61 ']'
    37. + BAR='\033[3;44m '
    38. + let i=3+1
    39. + '[' 4 -le 62 ']'
    40. + '[' 4 = 61 ']'
    41. + BAR='\033[3;44m '
    42. + let i=4+1
    43. + '[' 5 -le 62 ']'
    44. + '[' 5 = 61 ']'
    45. + BAR='\033[3;44m '
    46. + let i=5+1
    47. + '[' 6 -le 62 ']'
    48. + '[' 6 = 61 ']'
    49. + BAR='\033[3;44m '
    50. + let i=6+1
    51. + '[' 7 -le 62 ']'
    52. + '[' 7 = 61 ']'
    53. + BAR='\033[3;44m '
    54. + let i=7+1
    55. + '[' 8 -le 62 ']'
    56. + '[' 8 = 61 ']'
    57. + BAR='\033[3;44m '
    58. + let i=8+1
    59. + '[' 9 -le 62 ']'
    60. + '[' 9 = 61 ']'
    61. + BAR='\033[3;44m '
    62. + let i=9+1
    63. + '[' 10 -le 62 ']'
    64. + '[' 10 = 61 ']'
    65. + BAR='\033[3;44m '
    66. + let i=10+1
    67. + '[' 11 -le 62 ']'
    68. + '[' 11 = 61 ']'
    69. + BAR='\033[3;44m '
    70. + let i=11+1
    71. + '[' 12 -le 62 ']'
    72. + '[' 12 = 61 ']'
    73. + BAR='\033[3;44m '
    74. + let i=12+1
    75. + '[' 13 -le 62 ']'
    76. + '[' 13 = 61 ']'
    77. + BAR='\033[3;44m '
    78. + let i=13+1
    79. + '[' 14 -le 62 ']'
    80. + '[' 14 = 61 ']'
    81. + BAR='\033[3;44m '
    82. + let i=14+1
    83. + '[' 15 -le 62 ']'
    84. + '[' 15 = 61 ']'
    85. + BAR='\033[3;44m '
    86. + let i=15+1
    87. + '[' 16 -le 62 ']'
    88. + '[' 16 = 61 ']'
    89. + BAR='\033[3;44m '
    90. + let i=16+1
    91. + '[' 17 -le 62 ']'
    92. + '[' 17 = 61 ']'
    93. + BAR='\033[3;44m '
    94. + let i=17+1
    95. + '[' 18 -le 62 ']'
    96. + '[' 18 = 61 ']'
    97. + BAR='\033[3;44m '
    98. + let i=18+1
    99. + '[' 19 -le 62 ']'
    100. + '[' 19 = 61 ']'
    101. + BAR='\033[3;44m '
    102. + let i=19+1
    103. + '[' 20 -le 62 ']'
    104. + '[' 20 = 61 ']'
    105. + BAR='\033[3;44m '
    106. + let i=20+1
    107. + '[' 21 -le 62 ']'
    108. + '[' 21 = 61 ']'
    109. + BAR='\033[3;44m '
    110. + let i=21+1
    111. + '[' 22 -le 62 ']'
    112. + '[' 22 = 61 ']'
    113. + BAR='\033[3;44m '
    114. + let i=22+1
    115. + '[' 23 -le 62 ']'
    116. + '[' 23 = 61 ']'
    117. + BAR='\033[3;44m '
    118. + let i=23+1
    119. + '[' 24 -le 62 ']'
    120. + '[' 24 = 61 ']'
    121. + BAR='\033[3;44m '
    122. + let i=24+1
    123. + '[' 25 -le 62 ']'
    124. + '[' 25 = 61 ']'
    125. + BAR='\033[3;44m '
    126. + let i=25+1
    127. + '[' 26 -le 62 ']'
    128. + '[' 26 = 61 ']'
    129. + BAR='\033[3;44m '
    130. + let i=26+1
    131. + '[' 27 -le 62 ']'
    132. + '[' 27 = 61 ']'
    133. + BAR='\033[3;44m '
    134. + let i=27+1
    135. + '[' 28 -le 62 ']'
    136. + '[' 28 = 61 ']'
    137. + BAR='\033[3;44m '
    138. + let i=28+1
    139. + '[' 29 -le 62 ']'
    140. + '[' 29 = 61 ']'
    141. + BAR='\033[3;44m '
    142. + let i=29+1
    143. + '[' 30 -le 62 ']'
    144. + '[' 30 = 61 ']'
    145. + BAR='\033[3;44m '
    146. + let i=30+1
    147. + '[' 31 -le 62 ']'
    148. + '[' 31 = 61 ']'
    149. + BAR='\033[3;44m '
    150. + let i=31+1
    151. + '[' 32 -le 62 ']'
    152. + '[' 32 = 61 ']'
    153. + BAR='\033[3;44m '
    154. + let i=32+1
    155. + '[' 33 -le 62 ']'
    156. + '[' 33 = 61 ']'
    157. + BAR='\033[3;44m '
    158. + let i=33+1
    159. + '[' 34 -le 62 ']'
    160. + '[' 34 = 61 ']'
    161. + BAR='\033[3;44m '
    162. + let i=34+1
    163. + '[' 35 -le 62 ']'
    164. + '[' 35 = 61 ']'
    165. + BAR='\033[3;44m '
    166. + let i=35+1
    167. + '[' 36 -le 62 ']'
    168. + '[' 36 = 61 ']'
    169. + BAR='\033[3;44m '
    170. + let i=36+1
    171. + '[' 37 -le 62 ']'
    172. + '[' 37 = 61 ']'
    173. + BAR='\033[3;44m '
    174. + let i=37+1
    175. + '[' 38 -le 62 ']'
    176. + '[' 38 = 61 ']'
    177. + BAR='\033[3;44m '
    178. + let i=38+1
    179. + '[' 39 -le 62 ']'
    180. + '[' 39 = 61 ']'
    181. + BAR='\033[3;44m '
    182. + let i=39+1
    183. + '[' 40 -le 62 ']'
    184. + '[' 40 = 61 ']'
    185. + BAR='\033[3;44m '
    186. + let i=40+1
    187. + '[' 41 -le 62 ']'
    188. + '[' 41 = 61 ']'
    189. + BAR='\033[3;44m '
    190. + let i=41+1
    191. + '[' 42 -le 62 ']'
    192. + '[' 42 = 61 ']'
    193. + BAR='\033[3;44m '
    194. + let i=42+1
    195. + '[' 43 -le 62 ']'
    196. + '[' 43 = 61 ']'
    197. + BAR='\033[3;44m '
    198. + let i=43+1
    199. + '[' 44 -le 62 ']'
    200. + '[' 44 = 61 ']'
    201. + BAR='\033[3;44m '
    202. + let i=44+1
    203. + '[' 45 -le 62 ']'
    204. + '[' 45 = 61 ']'
    205. + BAR='\033[3;44m '
    206. + let i=45+1
    207. + '[' 46 -le 62 ']'
    208. + '[' 46 = 61 ']'
    209. + BAR='\033[3;44m '
    210. + let i=46+1
    211. + '[' 47 -le 62 ']'
    212. + '[' 47 = 61 ']'
    213. + BAR='\033[3;44m '
    214. + let i=47+1
    215. + '[' 48 -le 62 ']'
    216. + '[' 48 = 61 ']'
    217. + BAR='\033[3;44m '
    218. + let i=48+1
    219. + '[' 49 -le 62 ']'
    220. + '[' 49 = 61 ']'
    221. + BAR='\033[3;44m '
    222. + let i=49+1
    223. + '[' 50 -le 62 ']'
    224. + '[' 50 = 61 ']'
    225. + BAR='\033[3;44m '
    226. + let i=50+1
    227. + '[' 51 -le 62 ']'
    228. + '[' 51 = 61 ']'
    229. + BAR='\033[3;44m '
    230. + let i=51+1
    231. + '[' 52 -le 62 ']'
    232. + '[' 52 = 61 ']'
    233. + BAR='\033[3;44m '
    234. + let i=52+1
    235. + '[' 53 -le 62 ']'
    236. + '[' 53 = 61 ']'
    237. + BAR='\033[3;44m '
    238. + let i=53+1
    239. + '[' 54 -le 62 ']'
    240. + '[' 54 = 61 ']'
    241. + BAR='\033[3;44m '
    242. + let i=54+1
    243. + '[' 55 -le 62 ']'
    244. + '[' 55 = 61 ']'
    245. + BAR='\033[3;44m '
    246. + let i=55+1
    247. + '[' 56 -le 62 ']'
    248. + '[' 56 = 61 ']'
    249. + BAR='\033[3;44m '
    250. + let i=56+1
    251. + '[' 57 -le 62 ']'
    252. + '[' 57 = 61 ']'
    253. + BAR='\033[3;44m '
    254. + let i=57+1
    255. + '[' 58 -le 62 ']'
    256. + '[' 58 = 61 ']'
    257. + BAR='\033[3;44m '
    258. + let i=58+1
    259. + '[' 59 -le 62 ']'
    260. + '[' 59 = 61 ']'
    261. + BAR='\033[3;44m '
    262. + let i=59+1
    263. + '[' 60 -le 62 ']'
    264. + '[' 60 = 61 ']'
    265. + BAR='\033[3;44m '
    266. + let i=60+1
    267. + '[' 61 -le 62 ']'
    268. + '[' 61 = 61 ']'
    269. + BAR='\033[3;44m \033[7;39m'
    270. + BAR='\033[3;44m \033[7;39m '
    271. + let i=61+1
    272. + '[' 62 -le 62 ']'
    273. + '[' 62 = 61 ']'
    274. + BAR='\033[3;44m \033[7;39m '
    275. + let i=62+1
    276. + '[' 63 -le 62 ']'
    277. + BAR='\033[3;44m \033[7;39m \033[0;39m'
    278. + echo -en '\r\033[3;44m \033[7;39m \033[0;39m 98.00%'
    279. 98.00%+ isalive 35785

  • 相关阅读:
    Go 语言初探:从基础到实战
    SV--数组队列代码练习(8/14)
    ETL性能优化
    java-net-php-python-jsp网络考试系统计算机毕业设计程序
    JavaWeb之Servlet-----(2)
    javascript-基础知识
    【Java集合类】之 HashSet以及底层逻辑分析
    K8S基础架构租赁(Lease )
    数学建模国赛拿奖关键tips,错过这7条可能与国奖无缘!
    计算机毕业设计选题推荐-springboot 小说阅读平台
  • 原文地址:https://blog.csdn.net/alwaysbefine/article/details/130903816