bash - 为 BASH 脚本导出系统日志文件创建进度条
问题描述
基本上对于提取和导出的一组系统日志,我需要通过打印字符“#”来指示脚本进度。这最终应该会创建一个宽度为 60 的进度条。如下所示:#############################################
另外,我需要从左到右构建字符,以指示脚本的进度。
此代码所基于的问题/问题如下:“使用单独的调用wevtutil el
来获取日志数量的计数并将其缩放到例如 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
我尝试了诸如 using 之类的方法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 个文件之后使用新的“#”更新状态栏:
- 我的下面有 719 个文件,
/bin
所以#'s
我的状态栏中应该有 35 个(处理完成后我会在最后添加一个额外的文件#
) - 我们将使用一些
tput
命令来处理光标/行的移动,以及从一行中删除以前的输出 - 为了打印状态栏,我预先计算了数量,
#'s
然后使用 2 个变量 ...$barspace
用于空格,$barhash
用于#'s
; 对于每 20 个文件,我去掉一个空格$barspace
并添加一个#
到$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
我无法在任何(互联网)小提琴网站上使用上述内容(基本上在tput
使用基于 Web 的“终端”时遇到问题)。
这是一个显示行为的 gif ...
笔记:
- 该脚本确实将每个文件名打印到标准输出,但由于该脚本实际上并没有对有问题的文件做任何事情a)
printfs
发生得非常快,b)视频/gif只捕获(相对)少数转瞬即逝的图像(“Duh,Mark !”?) - 最后一个
printf "file: -- DONE --\n"
是在我创建 gif 之后添加的,我很懒惰,没有生成和上传新的 gif
推荐阅读
- html - CSS背景颜色不粘
- batch-file - 每次运行时将数字添加到文件名的批处理文件
- python - 进行正则表达式替换的最佳方法
- blazor - 在每次页面加载时首先需要调用的东西会在 blazor 中出现在哪里?
- ruby-on-rails - rails nested_attributes form 找不到 id
- javascript - 父 useEffect 函数范围中的 useLocation 更改,但嵌套函数使用旧值
- python - 使用 Beautiful Soup/Selenium 对动态表进行增补时,我无法获得完整的 html 代码
- javascript - 如何将表单组数据传递给另一个组件中的提交按钮(Angular 7)
- python - 如何在不先下载文件的情况下使用 pygrib 打开 GRIB 文件?
- angular - Angular ngIf 在 else 中有多个语句