2

I'm currently writing a Bash script. I want to download a file while printing text. For example, consider this script:

echo -e "---------------------------"
echo -e "Your file downloading..." 
echo -e "---------------------------"
wget example.com/1gbfile

In the second echo each . should be printed successively every second till the download finishes. If the number of . becomes three, like this: ..., it should be reset to only one . and continue the loop.

BeastOfCaerbannog
  • 12,964
  • 10
  • 49
  • 77
Erikli
  • 419
  • 1
  • 4
  • 11
  • So the built-in indicator by `wget` doesn't do the job for you? – Artur Meinild Nov 16 '22 at 14:43
  • 1
    I think the OP is actually interested in creating a "spinner like" animation, like this: https://askubuntu.com/questions/623933/how-to-create-a-rotation-animation-using-shell-script/ – Artur Meinild Nov 16 '22 at 14:46
  • 2
    Also https://stackoverflow.com/q/73723689/7552 – glenn jackman Nov 16 '22 at 15:08
  • @ArturMeinild Yea, we can call it like that. I'm gonna obfuscate my script because of some private things like download server. And wget shows the download server etc. So I wanted to make something cool like this. – Erikli Nov 16 '22 at 15:51

1 Answers1

4
Main script:

Create the following script as the source for your progress/bouncing bar (I called it bash-progress):

#!/bin/bash

# Initial configuration variables

# Set time interval for progress delay (in fraction of seconds)
time_delay=".2"

# Set left and right brackets (1 character)
  lb="["
#  lb="("
#  lb=" "
  rb="]"
#  rb=")"
#  rb=" "

# Function to show bouncing bar while running command in the background
show_bouncer() {
  # If no argument is given, then this is run on the last command - else provide PID
  if [[ -z $1 ]]
  then
    PID=$!
  else
    PID=$1
  fi
  ii=0
  # Define bouncer array (3 characters)
  bo=('.  ' '.. ' '...' ' ..' '  .' ' ..' '...' '.. ')
#  bo=('⠄  ' '⠂⠄ ' '⠁⠂⠄' '⠂⠂⠂' '⠄⠂⠁' ' ⠄⠂' '  ⠄' '   ')
#  bo=('⡇  ' '⣿  ' '⣿⡇ ' '⢸⣿ ' ' ⣿⡇' ' ⢸⡇' '  ⡇' '   ')
  # True while the original command is running
  while [[ -d "/proc/$PID" ]]
  do
    ch="${bo[(ii++)%${#bo[@]}]}"
    printf "%b" " ${lb}${ch}${rb}"
    sleep "$time_delay"
    # Adjust backspaces to bouncer length + 3
    printf "\b\b\b\b\b\b"
  done
}

The script can work in 2 ways: Either by using the PID of the last command run, or with a given PID. The most common use is with the last command.

Using it:

So you simply create your other script like this:

#!/bin/bash

# Include Bash progress bars - or include the entire source in your script.
source "./bash-progress"

your_command_here &
show_bouncer

It's important to run the command in the background, since it then moves on immediately to show the bouncer.

You can easily test it with a sleep command:

#!/bin/bash

# Include Bash progress bars - or include the entire source in your script.
source "./bash-progress"

sleep 5 &
show_bouncer
Bonus info:

To use with a PID other than the last one, you can use pgrep (-n for newest and -x for exact match) to find the latest instance of the process like this:

#!/bin/bash

# Include Bash progress bars - or include the entire source in your script.
source "./bash-progress"

your_command &
do_something_else
do_anything_meanwhile
show_bouncer $(pgrep -nx "your_command")
Artur Meinild
  • 21,605
  • 21
  • 56
  • 89
  • 1
    Really nice, simple and customizable script! – BeastOfCaerbannog Nov 17 '22 at 09:29
  • 1
    Thanks. I have a slew of other variations, I think I'll put it on Gitlab when I get around to it, and link here. – Artur Meinild Nov 17 '22 at 09:30
  • It works perfectly fine. Thank you so much! That's what I was looking for exactly!! – Erikli Nov 17 '22 at 10:09
  • @ArturMeinild Umm, I'm sorry. I don't want to be sassy but how can I use it for the second echo? I tried to implement it but i screwed it up :/ – Erikli Nov 17 '22 at 10:14
  • I'm sorry, but if you want to implement it like that (where you're going to go back and redraw a specific area of the screen where you have already printed), then that's something you'll have to research yourself. My implementation is more "linear", so that the bouncing bar is the last thing that's printed while it waits. – Artur Meinild Nov 17 '22 at 10:21
  • In that case, you need to modify the print function inside the `while` loop to print exactly what you like. But you need to figure that out yourself. – Artur Meinild Nov 17 '22 at 10:48