为 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
基本上,对于提取和导出的一定数量的系统日志,我需要通过打印字符“#”来指示脚本进度。这最终应该创建一个宽度为 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