Karolis
Karolis

Reputation: 9562

Understanding the difference over output to stdout and a regular file

This is the output of ls command:

$ ls
addr.sh  hello.txt  test.sh  xxx.txt

Here we have the same command with redirection to stderr:

$ ls 1>&2
addr.sh  hello.txt  test.sh  xxx.txt

Which produces pretty much the same output.

However redirection to a regular file causes ls to produce a multi-line output:

$ ls > xxx.txt
$ cat xxx.txt
addr.sh
hello.txt
test.sh
xxx.txt

Why and what is happening behind the scenes?

Upvotes: 1

Views: 110

Answers (1)

KamilCuk
KamilCuk

Reputation: 140880

Why

Because someone programmed it that way.

what is happening

Your implementation of ls checks if standard output is connected to a terminal device. If it is, it outputs a pretty printed output separated by spaces in a column-like fashion. If the output isn't a terminal device, it outputs a newline separated list.*

Checking if a file decriptor is opened on a terminal can be done with test -t FD command that internally calls isatty() C function.

ls basically works like:

{ if [ -t 1 ]; then ls -C; else ls -1; fi }
# From man ls:
# -C     list entries by columns
# -1     list one file per line.

Many utilities change their behavior when the output is not a terminal device.

*Note that POSIX ls specification mandates the output to be list of one entry per file when the output is not a terminal The default format shall be to list one entry per line to standard output; the exceptions are to terminals [...].

behind the scenes?

I assume you have coreutils ls implementaion. At coreutils/ls.c#L1886 program just checks if isatty(STDOUT_FILENO) and depending on that sets quoting style and column-like or newline-like output.

Upvotes: 3

Related Questions