1

Essentially for a set number of systems logs pulled and exported I need to indicate the scripts progress by printing a character "#". This should eventually create a progress bar with a width of 60. Something like what's presented below: ############################################# ,additionally I need the characters to build from left to right indicating the progression of the script.

The Question/Problem that this code was based off of goes as follows: "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

I've attempted methods such as using echo -ne "#", and printf "#%0.s" however the issue that I encounter is that the "#" characters gets printed with each instance of the name of the log file being retrieved; also the pattern is printed vertically rather than horizontally.

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"

I tried previously integrating this code into the first block but no luck. But something tells me that I don't need to establish a whole new loop, I keep thinking that the first block of code only needs a few lines of modification. Anyhow sorry for the lengthy explanation, please let me know if anything additional is needed for assistance--Thank you.

dex
  • 11
  • 6
  • 1
    What are you trying to make the display look like? Are you trying to put the current filename and `#######` bar on different lines? If so, you need some way to bounce back & forth to update both; if not, you need to figure out how to fit both on a single line. – Gordon Davisson Jan 01 '20 at 01:22
  • Yes that is correct, if possible I would like to display both the current file being fetched/exported and the progress bar "###..." on different lines. Sorry if my question was incorrectly formatted or poorly, worded this is the first time asking for help via the web. – dex Jan 01 '20 at 18:12

1 Answers1

2

For the sake of this answer I'm going to assume the desired output is a 2-liner that looks something like:

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

The following may not work for everyone as it comes down to individual terminal attributes and how they can(not) be manipulated by tput (ie, ymmv) ...

For my sample script I'm going to loop through the contents of /bin, printing the name of each file as I process it, while updating the status bar with a new '#' after each 20 files:

  • there are 719 files under my /bin so there should be 35 #'s in my status bar (I add an extra # at the end once processing has completed)
  • we'll use a few tput commands to handle cursor/line movement, plus erasing previous output from a line
  • for printing the status bar I've pre-calculated the number of #'s and then use 2 variables ... $barspace for spaces, $barhash for #'s; for each 20 files I strip a space off $barspace and add a single # to $barhash; by (re)printing these 2x variables every 20x files I get the appearance of a moving status bar

Putting this all together:

$ 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"

NOTE: While testing I had to periodically reset my terminal in order for the tput commands to function properly, eg:

$ reset
$ statbar

I couldn't get the above to work on any of the (internet) fiddle sites (basically having problems getting tput to work with the web-based 'terminals').

Here's a gif displaying the behavior ...

enter image description here

NOTES:

  • the script does print every filename to stdout but since this script isn't actually doing anything with the files in question a) the printfs occur quite rapidly and b) the video/gif only captures a (relatively) few fleeting images ("Duh, Mark!" ?)
  • the last printf "file: -- DONE --\n" was added after I created the gif, and I'm being lazy by not generating and uploading a new gif
markp-fuso
  • 28,790
  • 4
  • 16
  • 36
  • I tried modifying your code a bit according to what I need the progress bar to be monitoring. For the most part it works EXCEPT towards the end of the script when one last "#" is needed to complete the progress bar, I get the output ```[# ]``` followed by a complete a 90% complete status bar ```[################## ]```. That aside I appreciate the assistance provided thus far I'm just trying to figure out why this keeps occurring. – dex Jan 06 '20 at 21:25
  • hard to say what the issue might be without seeing the actual code; the single `#` output sounds like there may be a typo in the `${barhash}` reference, eg, `${barash}#` (missing the first 'h') will result in a single `#` – markp-fuso Jan 06 '20 at 21:31
  • Sorry kinda new to Stack and having issues with the code block syntax i'm still digging on how to get it working but the issues seems to be occurring from ``` tput rc ``` to ```printf "[${barhash}${barspace}]\n" ``` , right after the while loop. Also I noticed that ```printf "file: -- DONE --\n"```, is outputting as ```file: -- DONE --code``` --PS Double checked the syntax and variables everything seems to be legit (i.e. no spelling errors) – dex Jan 06 '20 at 22:11
  • I've cut-n-pasted directly from my answer into my bash/cmd window, run the script, and it works as expected, so it's hard to ascertain what the issue is (eg, a typo in the code changes, something different with your version of bash, etc) without seeing all of your modified code – markp-fuso Jan 06 '20 at 22:17
  • Alright let me see if there is a way that I can post a descent chunk of code here, although it seems I am limited by the amount of characters I can use. Do you think it could be because I'm using "Git Bash"? – dex Jan 06 '20 at 22:25
  • don't cut-n-paste into this comment window; either add a section on the end of your question (above), or open/create a new question – markp-fuso Jan 06 '20 at 22:38
  • Here are two lines that I added to the while loop that could be affecting things. 1.) ```filename="${filename%$'\r'}"``` 2.) ```printf "log files: ${filename}${erase}\r\n"```, in this order directly after the ```tput rc``` within the while loop. I think this could be the source of the problem – dex Jan 06 '20 at 22:41
  • if you added a line to the output (ie, total of 3 lines of output constantly being overwritten), then you likely need to take into consideration that 3rd line when printing the last couple lines of output (after the `while` loop); whether you print that 3rd line again, skip past with a blank line (and no `erase`), or print something new to the 3rd line ... depends on what you expect to see in the **final** 3 lines of ourput ... – markp-fuso Jan 06 '20 at 22:41
  • 1
    I will keep tweaking the code I think I may have found the source the error but will post a new question if the issue continues to persist. – dex Jan 06 '20 at 22:51