Tux

...making Linux just a little more fun!

Two-cent Tip: bash script to create animated rotating mark

Mulyadi Santosa [mulyadi.santosa at gmail.com]


Sat, 24 Oct 2009 16:34:04 +0700

During my boring saturday, I was thinking to create simple animated cycling mark. Here's the script:

$ while(true); do for a in \\ \| \/ -; do echo -n $a; sleep 1 ; echo
-n -e \\r ; done; done

Notice the usage of escaped "\r" (carriage return) and "-n" option to display continous marks at the same line and at the same column

-- 
regards,
Freelance Linux trainer and consultant

blog: the-hydra.blogspot.com training: mulyaditraining.blogspot.com


Top    Back


Thomas Adam [thomas.adam22 at gmail.com]


Sat, 24 Oct 2009 11:49:00 +0100

2009/10/24 Mulyadi Santosa <mulyadi.santosa@gmail.com>:

> During my boring saturday, I was thinking to create simple animated
> cycling mark. Here's the script:
>
> $ while(true); do for a in \\ \| \/ -; do echo -n $a; sleep 1 ; echo
> -n -e \\r ; done; done
>
> Notice the usage of escaped "\r" (carriage return) and "-n" option to
> display continous marks at the same line and at the same column

Hmm. Use printf. You stand a better chance of this not sucking when running elsewhere:

a=1
sp="/-\|"
echo -n ' '
while true
do
    printf "\b${sp:a++%${#sp}:1}"
done

... add as much sleep in there as you need,

-- Thomas Adam


Top    Back


Mulyadi Santosa [mulyadi.santosa at gmail.com]


Sun, 25 Oct 2009 00:03:39 +0700

On Sat, Oct 24, 2009 at 5:49 PM, Thomas Adam <thomas.adam22@gmail.com> wrote:

>    printf "\b${sp:a++%${#sp}:1}"
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Slick! OK, I am not pretending to be a Bash genius here, but here's an explanation for ones who still confused on what the above printf line doing:

- first, it does backspace (the "\b"), so it erases one character backward

- then it pick one character from the "sp" array. It is done by dividing current value of "a" with the length of "sp" array. So, for the first iteration, it will yield "1". The ":1" means we pick 1 character only. We get "/" for the first iteration.

- Then "a" is incremented (remember, ++ is suffix here) and the above steps are repeated.

NB: Thanks for the excellent printf trick, Thomas!

-- 
regards,
Freelance Linux trainer and consultant

blog: the-hydra.blogspot.com training: mulyaditraining.blogspot.com


Top    Back


Ben Okopnik [ben at linuxgazette.net]


Thu, 29 Oct 2009 21:32:19 -0400

On Sat, Oct 24, 2009 at 11:49:00AM +0100, Thomas Adam wrote:

> 
> Hmm.  Use printf.  You stand a better chance of this not sucking when
> running elsewhere:
> 
> ```
> a=1
> sp="/-\|"
> echo -n ' '
> while true
> do
>     printf "\b${sp:a++%${#sp}:1}"
> done
> '''
> 
> ... add as much sleep in there as you need,

Very pretty - although unreadable to anyone not well up on parameter substitution. :) As to the delay, most distros unfortunately provide only a crude 'sleep INT' (although some, like Ubuntu, allow a float as an argument) - which makes the above look crude and jerky.

A long time ago, I hacked up a simple 'usleep' shell function that's still useful for things like this. It works with fractions of a second, e.g. "usleep 0.25".

usleep () { /usr/bin/perl -we'select undef, undef, undef, pop' ""; }
-- 
* Ben Okopnik * Editor-in-Chief, Linux Gazette * https://LinuxGazette.NET *


Top    Back


Ben Okopnik [ben at linuxgazette.net]


Thu, 29 Oct 2009 21:16:17 -0400

On Sat, Oct 24, 2009 at 04:34:04PM +0700, Mulyadi Santosa wrote:

> During my boring saturday, I was thinking to create simple animated
> cycling mark. Here's the script:
> 
> $ while(true); do for a in \\ \| \/ -; do echo -n $a; sleep 1 ; echo
> -n -e \\r ; done; done
> 
> Notice the usage of escaped "\r" (carriage return) and "-n" option to
> display continous marks at the same line and at the same column

That's pretty similar to what I show my students to demonstrate the utility of the "\r" metacharacter. I also show them how to use "\b", since "\r" will only work if you're doing this starting at the beginning of the line - and this output is centered on the screen.

#!/bin/sh
# Created by Ben Okopnik on Thu Nov  1 07:18:17 EST 2001
# Shows a full-line "progress spinner"
 
msg="Please be patient: the computer is thinking..."
# Determine the number of lines and columns for the terminal
eval "`resize`"
# Calculate the indent
length=`expr \( $COLUMNS - ${#msg} \) / 2`
indent=`printf "%${length}s"`
 
a="`echo $msg|sed 's#.#.#g'`"
b="`echo $msg|sed 's#.#o#g'`"
c="`echo $msg|sed 's#.#O#g'`"
d="`echo $msg|sed 's#.#o#g'`"
e="`echo $msg|sed 's#.#\\\b#g'`"
 
printf "$indent$msg\n"
 
for n in 1 2 3 4
do
	for x in $a $b $c $d
	do 
		printf "$indent%b%b" $x $e
		sleep 1
		printf "\r"
	done
done
 
printf "${indent}All life on Earth will now be destroyed.$indent\n"
printf "${indent}Thank you for waiting.\n"
-- 
* Ben Okopnik * Editor-in-Chief, Linux Gazette * https://LinuxGazette.NET *


Top    Back