Holding cursor position on one line

Hi there.

It's easier to explain this with a pseudo code, I hope this makes sense:

var1=hello
echo $var1

some kind of loop
  echo loop counter
done

How do I hold the cursor position immediately behind the last output so I'd get something like:
hello123456789

DOS used to use "," as a tab between printed data and ";" held the cursor in place without any carriage return. Is there a similar thing in Bash?

Thanks again.

echo -n doesn't add a newline:

var1=hello
echo -n $var1

for (( i=1; i<=9; i++ )) ; do echo -n $i; done

By definition, echo appends a <newline> character to its input arguments in the output it produces. Try using printf instead of echo :

var1=hello
printf '%s' "$var1"

cnt=1
some kind of loop
  printf '%d' "$cnt"
  cnt=$((cnt + 1))
done

Some non-standard implementations of echo provide an option to avoid printing the terminating <newline>, but printf as shown above should work portably no matter what operating system or shell you're using.

Note that showing us your actual code instead of pseudo-code and telling us what operating system and shell you're using is always much clearer than trying to guess at how pseudo-code might relate to actual code.

I usually do something like this:

SPIN=".oOo."

S=0

while true
do
        printf "Doing something [%s]\r" "${SPIN:$S:1}"
        S=$(( (S+1) % ${#SPIN}))
        sleep 0.1
done

Note the \r, that's a carriage return, it returns the cursor to the beginning of the line without moving it down one line.

2 Likes

Another way might be to use tput cup row column to set the cursor position on the screen, but you have to know what shape screen you have and it's usually better to clear it before you begin so you know that there is nothing to overwrite.

Yet another an alternate could be to just output a dot or other character without the new-line each time round the loop with printf

How much output would you expect, or iterations round your loop? Are you watching a file grow, for instance?

You could:-

#!/bin/bash

filename=/path/to/bigfile

[ ! -f $filename ] && touch $filename             # Make sure it exists
while true
do
   printf "\r$filename=$(stat -c %s $filename) bytes"
   sleep 1
done

progress_pid=$!

# Do whatever to generate the large file now, e.g. a tar or wget etc.

kill $watcher_pid
echo ; echo "Watcher process ended."

This will show the file growing until your script carries on and terminates the watcher.

Does any of these help? it really depends on what you eventually want to do. If you can put it in context, we might refine our suggestions.

Kind regards,
Robin

On VT102-compatible terminals / emulators, you might also want to consider cursor controls - see man console_codes .