Typically, when displaying data to screen, a newline is treated as if there is also a carriage return.
Consider:
$ printf "aaa\nbbb\n"
aaa
bbb
$ printf "aaa\nbbb\n" | od -c
0000000 a a a \n b b b \n
0000010
$ printf "aaa\nbbb\n" | tr -d '\r'
aaa
bbb
$
Now:
$ script -B/dev/null -fqc 'printf "aaa\nbbb\n"'
aaa
bbb
$ script -B/dev/null -fqc 'printf "aaa\nbbb\n"' | od -c
0000000 a a a \r \n b b b \r \n
0000012
$ script -B/dev/null -fqc 'printf "aaa\nbbb\n"' | tr -d '\r' | od -c
0000000 a a a \n b b b \n
0000010
$
But:
$ script -B/dev/null -fqc 'printf "aaa\nbbb\n"' | tr -d '\r'
aaa
bbb
$ script -B/dev/null -fqc 'printf "aaa\nbbb\n"' | tr -d '\r' >log
$ od -c <log
0000000 a a a \n b b b \n
0000010
$ cat log
aaa
bbb
$
What is happening in the script
pipeline that causes different display behaviour for apparently-identical data?
Is there a simple-ish command that could be used in place of (or in addition to) tr -d '\r'
in the script
pipeline that would remove the extraneous carriage returns from the data stream while also re-enabling the normal stty onlcr
display behaviour when the pipeline destination is the screen?
The implementations of script
I have checked (util-linux and freebsd), both call cfmakeraw(3) if their stdin is a terminal.
On linux, it is specified that:
The cfmakeraw() function shall set the attributes of the termios structure referenced by termios_p as follows:
termios_p->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP |INLCR|IGNCR|ICRNL|IXON); termios_p->c_oflag &= ~OPOST; termios_p->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); termios_p->c_cflag &= ~(CSIZE|PARENB); termios_p->c_cflag |= CS8;
FreeBSD is less specific, saying:
The cfmakeraw() function sets the flags stored in the termios structure to a state disabling all input and output processing, giving a "raw I/O path"
To reverse these changes, calling stty
with desired settings in an appropriate part of the pipeline (as per @philippe's answer), is one option.
Another way may be to avoid the changes happening in the first place, by redirecting stdin from a non-terminal (eg. /dev/null
) so that cfmakeraw() is never called.
However, the util-linux documentation warns that running with stdin not connected to a terminal may cause problems in some situations.