master_latch
master_latch

Reputation: 444

Why does less change order of output?

I am running a python script which produces certain output when I run it in verbose mode. When I pipe the output to the less utility, the output is in a different order. For reference, the script is, if not exactly, very nearly this:

http://svn.apache.org/repos/asf/subversion/trunk/tools/client-side/change-svn-wc-format.py

Specifically, I get the "Data for the following field(s)" message and when I run it without piping the output to less, this message appears last. When I pipe the output to less, the output mysteriously appears first.

Can anybody explain this?

I have determined that the error message goes to stderr while the verbose messages go to stdout. However, even when I do:

./svnfixversion ./ 1.5 --verbose 2>&1 | less

the output is different from when I just leave off the | less. If the stderr is getting redirected to stdout, shouldn't less preserve the order?

Upvotes: 0

Views: 112

Answers (1)

Maxim Egorushkin
Maxim Egorushkin

Reputation: 136296

When you run:

./svnfixversion ./ 1.5 --verbose

its stdout is line buffered, stderr is non-buffered.

In:

./svnfixversion ./ 1.5 --verbose 2>&1 | less

its stdout is fully buffered, stderr is non-buffered.

The buffering mode of ./svnfixversion FILE* stdout is what makes the output different in these two cases.

If you want the second output to be identical to the first one, set stdout buffering mode to line buffered with stdbuf application:

stdbuf --output=L ./svnfixversion ./ 1.5 --verbose 2>&1 | less

In modern bash you can replace 2>&1 | with shorter |&.


What happens under the hood, is that at program start before main() is called glibc calls isatty(STDOUT_FILENO) to determine whether stdout is connected to a terminal. If so, stdout is line buffered, otherwise full buffered. stderr is always unbuffered.

Upvotes: 3

Related Questions