为 BASH 导出系统日志文件的脚本创建进度条

Creating a progress bar for BASH script exporting system log files

基本上,对于提取和导出的一定数量的系统日志,我需要通过打印字符“#”来指示脚本进度。这最终应该创建一个宽度为 60 的进度条。如下所示: ############################################# ,此外,我需要从左到右构建字符,以指示脚本的进度。

此代码基于的 Question/Problem 如下所示:"Use a separate invocation of wevtutil el to get the count of the number of logs and scale this to,say, a width of 60."

SYSNAM=$(hostname)
LOGDIR=${1:-/tmp/${SYSNAM}_logs}

i=0
LOGCOUNT=$( wevtutil el | wc -l )
x=$(( LOGCOUNT/60 ))

wevtutil el | while read ALOG
do
        ALOG="${ALOG%$'\r'}"
        printf "${ALOG}:\r"
        SAFNAM="${ALOG// /_}"
        SAFNAM="${SAFNAM//\//-}"
        wevtutil epl "$ALOG" "${SYSNAM}_${SAFNAM}.evtx"


done

我已经尝试过使用 echo -ne "#"printf "#%0.s" 等方法,但是我遇到的问题是“#”字符与日志文件名称的每个实例一起打印被检索;图案也是垂直打印的,而不是水平打印的。

LOGCOUNT=$( wevtutil el | wc -l )
x=$(( LOGCOUNT/60 ))

echo  -ne "["
for i in {1..60}
do
        if [[ $(( x*i )) != $LOGCOUNT ]]
        then
                echo -ne "#"
                #printf '#%0.s'
        fi

done
echo "]"
printf "\n"
echo "Transfer Complete."
echo "Total Log Files Transferred: $LOGCOUNT"

我之前尝试过将此代码集成到第一个块中,但没有成功。但有些东西告诉我,我不需要建立一个全新的循环,我一直认为第一段代码只需要修改几行。无论如何,对于冗长的解释感到抱歉,如果需要任何额外的帮助,请告诉我——谢谢。

为了这个答案,我假设所需的输出是一个 2-liner,看起来像:

$ statbar
file: /bin/cygdbusmenu-qt5-2.dll
[########                            ]

以下内容可能不适用于每个人,因为它归结为各个终端属性以及它们如何(不)被 tput(即 ymmv)操纵...

对于我的示例脚本,我将遍历 /bin 的内容,在我处理每个文件时打印它的名称,同时在每 20 个之后用新的“#”更新状态栏文件:

  • 我的 /bin 下有 719 个文件,所以我的状态栏中应该有 35 个 #'s(我在处理完成后在最后添加了一个额外的 #
  • 我们将使用一些 tput 命令来处理 cursor/line 移动,并从一行中删除先前的输出
  • 用于打印状态栏我预先计算了 #'s 的数量,然后使用 2 个变量... $barspace for spaces,$barhash对于 #'s;对于每 20 个文件,我从 $barspace 中删除一个 space,并在 $barhash 中添加一个 #;通过(重新)每 20x 个文件打印这些 2x 变量,我得到了移动状态栏的外观

综合起来:

$ cat statbar
clear              # make sure we have plenty of room to display our status bar;
                   # if we're at the bottom of the console/window and we cause the
                   # windows to 'scroll up' then 'tput sc/rc' will not work

tput sc            # save pointer/reference to current terminal line
erase=$(tput el)   # save control code for 'erase (rest of) line'

# init some variables; get a count of the number of files so we can pre-calculate the total length of our status bar

modcount=20
filecount=$(find /bin -type f | wc -l)

# generate a string of filecount/20+1 spaces (35+1 for my particular /bin)

barspace=

for ((i=1; i<=(filecount/modcount+1); i++))
do
        barspace="${barspace} "
done

barhash=           # start with no #'s for this variable

filecount=0        # we'll re-use this variable to keep track of # of files processed so need to reset

while read -r filename
do
        filecount=$((filecount+1))

        tput rc    # return cursor to previously saved terminal line (tput sc)

        # print filename (1st line of output); if shorter than previous filename we need to erase rest of line

        printf "file: ${filename}${erase}\n"

        # print our status bar (2nd line of output) on the first and every ${modcount} pass through loop; 

        if   [ ${filecount} -eq 1 ]
        then
                printf "[${barhash}${barspace}]\n"

        elif [[ $((filecount % ${modcount} )) -eq 0 ]]
        then
                # for every ${modcount}th file we ...

                barspace=${barspace:1:100000}         # strip a space from barspace
                barhash="${barhash}#"                 # add a '#' to barhash
                printf "[${barhash}${barspace}]\n"    # print our new status bar
        fi

done < <(find /bin -type f | sort -V)

# finish up the status bar (should only be 1 space left to 'convert' to a '#')

tput rc

printf "file: -- DONE --\n"

if [ ${#barspace} -gt 0 ]
then
        barspace=${barspace:1:100000}
        barhash="${barhash}#"
fi

printf "[${barhash}${barspace}]\n"

注意:在测试时,我必须定期重置我的终端才能使 tput 命令正常运行,例如:

$ reset
$ statbar

我无法让以上内容在任何(互联网)fiddle 网站上运行(基本上在让 tput 与基于网络的 'terminals' 一起工作时遇到问题) .

这是显示行为的 gif 图...

备注:

  • 脚本 确实 将每个文件名打印到标准输出,但由于该脚本实际上并未对相关文件执行任何操作 a) printfs 发生得非常快并且b) video/gif 仅捕获(相对)少数转瞬即逝的图像(“Duh,Mark!”?)
  • 最后一个 printf "file: -- DONE --\n" 是我创建 gif 后添加的,我很懒,没有生成和上传新的 gif