Differences between revisions 1 and 14 (spanning 13 versions)
Revision 1 as of 2007-05-02 23:23:02
Size: 725
Editor: redondos
Comment:
Revision 14 as of 2020-04-04 01:37:26
Size: 1692
Editor: GreyCat
Comment: mark examples by requirements, make the POSIX one really POSIX, make them functions, and show how to call them
Deletions are marked like this. Additions are marked like this.
Line 1: Line 1:
[[Anchor(faq34)]] <<Anchor(faq34)>>
Line 3: Line 3:
Sure. Sure!
Line 5: Line 6:
    i=1
    sp="/-\|"
    echo -n ' '
    while true
   
do
        echo -en "\b${sp:i++%${#sp}:1}"
    done
# Bash, with GNU sleep
spin() {
local i=0
  local sp='/-\|'
  local n=${#sp}
printf ' '
  sleep 0.1
while true; do
    printf '\b%s' "${sp:i++%n:1}"
    sleep 0.1
  
done
}
Line 14: Line 20:
You can also use \r instead of \b. You can use pretty much any character sequence you want as well. If you want it to slow down, put a {{{sleep}}} command inside the loop. Each time the loop iterates, it displays the next character in the `sp` string, wrapping around as it reaches the end. (`i` is the position of the current character to display and `${#sp}` is the [[BashFAQ/007|length]] of the `sp` string).
Line 16: Line 22:
To use as a function called from a loop on every iteration, for example: The `\b` string is replaced by a 'backspace' character. Alternatively, you could play with `\r` to go back to the beginning of the line.

To slow it down, the `sleep` command is included inside the loop (after the `printf`).

A POSIX equivalent would be:
Line 18: Line 29:
sp="/-\|" # POSIX sh
spin() {
  sp='/-\|'
  printf ' '
  sleep 1
  while true; do
    printf '\b%.1s' "$sp"
    sp=${sp#?}${sp%???}
    sleep 1
  done
}
}}}

One way to use these spinners in a script is to run them as background processes, and kill them when you're done. For example,

{{{
# POSIX sh
spin & spinpid=$!
# long-running commands here
kill "$spinpid"
}}}

If you already have a loop which does a lot of work, you can write a function that "advances" the spinner one step at a time, and call it at the beginning of each iteration:

{{{
# Bash, with GNU sleep
sp='/-\|'
Line 21: Line 58:
   echo -ne "\b${sp:sc++:1}"
   ((sc==4)) && sc=0
    printf "\b${sp:sc++:1}"
    ((sc==${#sp})) && sc=0
    sleep 0.1
Line 24: Line 62:
endspin() {
    printf '\r%s\n' "$*"
    sleep 0.1
}

until work_done; do
   spin
   some_work ...
done
endspin
Line 25: Line 73:
When printing the next output line (ie when the spin is over) use: {{{ echo -e "\r$line" }}} or: {{{ echo -en '\r'; echo "$line" }}}
Line 27: Line 74:
A similar technique can be used to build progress bars. A similar technique can be used to build [[BashFAQ/044|progress bars]].

----
CategoryShell

Can I do a spinner in Bash?

Sure!

# Bash, with GNU sleep
spin() {
  local i=0
  local sp='/-\|'
  local n=${#sp}
  printf ' '
  sleep 0.1
  while true; do
    printf '\b%s' "${sp:i++%n:1}"
    sleep 0.1
  done
}

Each time the loop iterates, it displays the next character in the sp string, wrapping around as it reaches the end. (i is the position of the current character to display and ${#sp} is the length of the sp string).

The \b string is replaced by a 'backspace' character. Alternatively, you could play with \r to go back to the beginning of the line.

To slow it down, the sleep command is included inside the loop (after the printf).

A POSIX equivalent would be:

# POSIX sh
spin() {
  sp='/-\|'
  printf ' '
  sleep 1
  while true; do
    printf '\b%.1s' "$sp"
    sp=${sp#?}${sp%???}
    sleep 1
  done
}

One way to use these spinners in a script is to run them as background processes, and kill them when you're done. For example,

# POSIX sh
spin & spinpid=$!
# long-running commands here
kill "$spinpid"

If you already have a loop which does a lot of work, you can write a function that "advances" the spinner one step at a time, and call it at the beginning of each iteration:

# Bash, with GNU sleep
sp='/-\|'
sc=0
spin() {
    printf "\b${sp:sc++:1}"
    ((sc==${#sp})) && sc=0
    sleep 0.1
}
endspin() {
    printf '\r%s\n' "$*"
    sleep 0.1
}

until work_done; do
   spin
   some_work ...
done
endspin

A similar technique can be used to build progress bars.


CategoryShell

BashFAQ/034 (last edited 2023-10-26 18:03:57 by emanuele6)