1

So, I was trying to create an aesthetic horizontally scrolling text in the console using bash. I wasn't sure how to go about this. here's an example:

Original string: Hi! How are you doing on this fine evening?

1st loop:
Hi! H
2nd:
i! Ho
3rd:
! How
4th:
 How 

and so on. How would I go about this? I would preferably have it delete the last printed loop so it is a smooth scrolling string. Any help would be appreciated! Thanks! (Also feel free to ask questions, this description was kinda bad :P)

1
  • Printing a raw \r is probably your friend here. What have you already tried? Commented Oct 22, 2022 at 3:11

3 Answers 3

1

This one is a bit hacky, but I believe it's the effect you are describing. In the output each of these lines will overwrite the previous entry so that it produces something like the old <marquee> tags, but in the terminal.

Hello There!
ello There! He
o There! Hello
There! Hello
ere! Hello The
e! Hello There
Hello There!
ello There! He
lo There! Hell
There! Hello
here! Hello Th
re! Hello Ther
! Hello There!
Hello There! H
llo There! Hel
o There! Hello
There! Hello T
here! Hello Th
e! Hello There
Hello There!
#!/bin/bash

function slice_loop () { ## grab a slice of a string, and if you go past the end loop back around
    local str="$1"
    local start=$2
    local how_many=$3
    local len=${#str};

    local result="";

    for ((i=0; i < how_many; i++))
    do
        local index=$(((start+i) % len)) ## Grab the index of the needed char (wrapping around if need be)
        local char="${str:index:1}" ## Select the character at that index
        local result="$result$char" ## Append to result
    done

    echo -n $result
}

msg="Hello There! ";
begin=0

while :
do
    slice=$(slice_loop "$msg" $begin 14);
    echo -ne "\r";
    echo -n $slice;
    echo -ne "              \r";
    sleep 0.08;
    ((begin=begin+1));
done

Save that in a file and run it and you should see the string "Hello There!" scroll past. It's a bit jittery but you can tweak that to make it a bit neater.

1

As the other said you should use echo or printf with carriage return \r.

So what you want is to print only 5 chars per loop you could use the script below for that behavior:

#!/bin/bash

null=$'\0'
text="Hi! How are you doing on this fine evening? ${null}"

#while :; do
count=0
for (( i = 0; i < "${#text}"; i++ )); do
   printf "\r%s" "${text:$i:5}"
   sleep 0.3
done
#done
echo

With this line printf "\r%s" "${text:$i:5}" I'm printing 5 characters per loop, where the $i is the current index and the 5 is the length of the string to print.
For example, if you print the text variable as follows:

printf "%s" "${text:0:5}"
#Output
Hi! H
printf "%s" "${text:1:5}"
#Output
i! Ho
#and so on

If you wish to print all the string and remove each character from left per loop you can use this script:

#!/bin/bash

null=$'\0'
text="Hi! How are you doing on this fine evening? ${null}"

#while :; do
count=0
for (( i = 0; i < "${#text}"; i++ )); do
   printf "\r%s" "${text:$i}"
   sleep 0.3
done
#done
echo

The code above will print:

In first loop:

Hi! How are you doing on this fine evening?

In second loop:

i! How are you doing on this fine evening?

In third loop:

! How are you doing on this fine evening?

and so on.

Note: The variable $null should be used to avoid printing at the end of the string its last character, in this case ?. And if you want a infinite loop your should uncomment the lines #while :; do and #done.

0

echo -e "\r" is your friend: \r is the carriage return symbol (imagine you're sitting in front of a typewriter!) which puts your cursor back at the beginning of the current line.

So,

#!/bin/bash
echo -n "foobar"
#     ^---------- don't print a newline at the end of the line!
sleep 1
echo -e -n "\rbaz"
#        ^------- don't print a newline at the end of the line!
#     ^---------- evaluate escape sequences like \r
echo -e -n "\rB"

will print foobar, wait a second, then overwrite foo with baz and then directly overwrite the small with a capital B, yielding Bazbar.

That should be all you need for a scroller!

If you really want to do animations, this will end up being too complicated. You'd want to write a program that uses a library that can actually modify arbitrary positions on your terminal. (n)curses is such a library – even Python has a module for it! I'd recommend checking it out. Here's an example.

0

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.