...making Linux just a little more fun!
Mulyadi Santosa [mulyadi.santosa at 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
-- regards,Freelance Linux trainer and consultant
blog: the-hydra.blogspot.com training: mulyaditraining.blogspot.com
Thomas Adam [thomas.adam22 at gmail.com]
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
Mulyadi Santosa [mulyadi.santosa at gmail.com]
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
Ben Okopnik [ben at linuxgazette.net]
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 * http://LinuxGazette.NET *
Ben Okopnik [ben at linuxgazette.net]
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 * http://LinuxGazette.NET *