11

I am looking for a script that creates a rotation animation using character /,-, | and \.

If you continuously switch between these characters it should look like its rotating. How to make this?

4 Answers 4

24

Use that script:

#!/bin/bash

chars="/-\|"

while :; do
  for (( i=0; i<${#chars}; i++ )); do
    sleep 0.5
    echo -en "${chars:$i:1}" "\r"
  done
done

The while loop runs infinite. The for loop runs trough each character of the string given in $chars. echo prints the character, with a carriage return \r, but without linebreak -n. -e forces echo to interpret escape sequences such as \r. There's a delay of 0.5 seconds between each change.

4
  • Clever, +1, but why not printf "%s\r" "${chars:$i:1}"?
    – terdon
    Commented May 15, 2015 at 17:26
  • 1
    @terdon first thought was echo... but of course printf works too. ^^
    – chaos
    Commented May 15, 2015 at 18:09
  • You can try it without the for loop: chars="/-\|"; while sleep 0.5; do echo -en "${chars:$(( i=(i+1) % ${#chars} )):1}" "\r"; done
    – eitan
    Commented Mar 9, 2021 at 16:47
  • The offset and length parts of ${var:offset:length} are already arithmetic expressions, so we can remove some of the syntax: echo -en "${chars: i = (i + 1) % ${#chars} : 1}" Commented Nov 16, 2022 at 14:57
22

Here's an example using \b, which tells the terminal emulator to move the cursor one column to the left, in order to keep overwriting the same character over and over.

#!/usr/bin/env bash

spinner() {
    local i sp n
    sp='/-\|'
    n=${#sp}
    printf ' '
    while sleep 0.1; do
        printf "%s\b" "${sp:i++%n:1}"
    done
}

printf 'Doing important work '
spinner &

sleep 10  # sleeping for 10 seconds is important work

kill "$!" # kill the spinner
printf '\n'

See BashFAQ 34 for more.

2
  • 7
    Great code. I would make one small modification, though. After running spinner &, I would store the pid in a local variable spinner_pid=$! and then replace the kill call with kill $spinner_pid &>/dev/null
    – dberm22
    Commented May 15, 2015 at 13:04
  • I would like to add tput civis #hide cursor and tput cnorm #show cursor Commented May 21, 2020 at 20:00
1

Since you don't explicitly ask for bash, a little plug for the fish shell, where this can be solved beautifully IMO:

set -l symbols ◷ ◶ ◵ ◴
while sleep 0.5
    echo -e -n "\b$symbols[1]"
    set -l symbols $symbols[2..-1] $symbols[1]
end

In this case, symbols is an array variable, and the contents if it are rotated/shifted, because $symbols[2..-1] are all entries but the first.

1

very minimal way of writing using printf

sh-5.1$ while true ; do for i in \\ "|" / "-"; do printf "$i" ; sleep 0.1 ; printf "\b" ; done ; done

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .