How to overwrite stdout using echo?

7,290

Solution 1

echo always outputs to its stdout1. echo foo always does a write(1, "foo\n").

When you do echo foo > file, the shell changes the stdout for the echo command to a new file file. echo foo then still does a write(1, "foo\n") but this time its stdout (its file descriptor 1) points to file, not to the stdout it inherits from the shell.

If you want to write to stdout without that stdout being redirected, just write:

echo foo

If you want the resource pointed to by stdout to be reopen (and truncated) before each echo, then that's trickier.

On Linux (and Linux only), you can do:

echo foo > /dev/fd/1
echo bar > /dev/fd/1
# now the file stdout points to (if it's a regular file) contains "bar"

On Linux, /dev/fd/1 is a symlink to the file that is open on stdout. So opening it again with > will truncate it (on other Unices, > /dev/fd/n is like dup2(n,1) so it won't truncate the file). That won't work if stdout goes to a socket though.

Otherwise, you can call ftruncate() on stdout (fd 1) to truncate it:

perl -e 'truncate STDOUT,0'
echo foo
perl -e 'truncate STDOUT,0'
echo bar

If instead, you want those words, when stdout is a terminal to overwrite each other on the screen, you can use terminal control characters to affect the cursor positioning.

 printf %s FOO
 printf '\r%s' BAR

will have BAR overwrite FOO because \r is the control characters that instructs the terminal to move the cursor to the beginning of the line.

If you do:

printf %s FOOBAR
printf '\r%s' BAZ

however, you'll see BAZBAR on the screen. You may want to use another control sequence to clear the line. While \r as meaning carriage return is universal, the control sequence to clear the screen varies from one terminal to the next. Best is to query the terminfo database with tput to find it out:

clr_eol=$(tput el)
printf %s FOOBAR
printf '\r%s%s' "$clr_eol" BAZ

1 if using the Korn or Z shell, another outputting command that supports writing to other file descriptors is print: print -u2 FOO for instance writes FOO to print's stderr. With echo and in Bourne-like shells, you can do echo >&2 FOO to achieve the same result. echo is still writing to its stdout, but its stdout has been made a duplicate of the shell's stderr using the >&2 shell redirection operator

Solution 2

You can say,

$ clear && printf "before" && sleep 1 && clear && printf "after\n"

For your Hello world,

$ clear && printf "Hello" && sleep 1 && clear && printf "World" && sleep 1 && clear && printf "I'm" && sleep 1 && clear && printf "Here\n"

Solution 3

If you're printing to a terminal anyway, you maybe just want to omit the newline (-n) and have an explicit carriage return instead:

echo -en 'hello, dear\r'; sleep 5; echo -en 'world\r'; echo

(Note that you'll want to space-pad your strings to overwrite them completely.)

Share:
7,290

Related videos on Youtube

user78050
Author by

user78050

Updated on September 18, 2022

Comments

  • user78050
    user78050 over 1 year

    We know to overwrite bar.txt, we can use this:

    echo "foo" > bar.txt
    

    but how can we overwrite to the standard output? I tried this command:

    echo "foo" >
    

    but it failed. I want this because I want to print something like this:

    Hello  
    
    world
    
    I'm 
    
    HERE 
    

    one word at a time and I want to delete the previous word (one word at a time on standard output).

    • Admin
      Admin over 9 years
      Your question is not clear. > operator won't append to the file actually it overwrites the file.And if you just say echo "foo" or echo "foo" >&1 it prints on stdout.
    • Admin
      Admin over 9 years
      I want to delete the word which printed on stdout then add another word
    • Admin
      Admin over 9 years
      Can you add the source of the output, how do you plan to get the sources?
    • Admin
      Admin over 9 years
      I'm under the impression you're confusing stdout (the default destination programs write their output to), with terminal.
  • Stéphane Chazelas
    Stéphane Chazelas over 9 years
    Note that not all echo implementations support -e or -n. Actually, Unix-conformant ones don't and you have to write echo '\b\b\b\bworld\c' there. See Why is printf better than echo for details.
  • Stéphane Chazelas
    Stéphane Chazelas over 9 years
    Note that not all echo implementations support -e or -n. Actually, Unix-conformant ones don't and you have to write echo '\b\b\b\bworld\c' there. See Why is printf better than echo for details.