So, I have always had doubts about how redirection works in the following situations:
I type "ls" and all the filenames are separated by white spaces:
test$ touch a b c
test$ ls
a b c
I use a ">" to redirect STDOUT to a file:
test$ ls > ls.txt
test$ cat ls.txt
a
b
c
ls.txt
It is interesting to see that the format changes, with the filenames separated by newline characters. It seems that the output is generated by ls -1
.
Why is the output in the latter case different from that in the former case? Can ls actually see the ">" symbol so it changes its behavior?
Redirection is a feature in Linux such that when executing a command, you can change the standard input/output devices. The basic workflow of any Linux command is that it takes an input and give an output. The standard input (stdin) device is the keyboard. The standard output (stdout) device is the screen.
Before a command is executed, its input and output may be redirected using a special notation interpreted by the shell. Redirection allows commands' file handles to be duplicated, opened, closed, made to refer to different files, and can change the files the command reads from and writes to.
Redirecting output to append to a file When the notation > > filename is added to the end of a command, the output of the command is appended to the specified file name, rather than writing over any existing data. The >> symbol is known as the append redirection operator.
The difference between a pipe and a redirect is that while a pipe passes standard output as standard input to another command, a redirect sends a output to a file or reads a file as standard input to a command.
ls
tests its output stream to see whether it is a terminal, and it modifies its behavior depending on that.
This is documented; the man
page for ls
documents several things that depend on whether the output is a terminal:
-C
(for multi-column output) is a default, otherwise -1
(one-column) is a default.-l
or -s
is used and the output is a terminal, a sum for all file sizes or blocks, respectively, is printed on a line before the listing.-q
is a default. This prints non-graphic characters as “?”. Otherwise, -v
and -w
are defaults. I am a bit unclear on the difference between -v
and -w
. The documentation I have says -v
forces “unedited printing of non-graphic characters” and -w
forces “raw printing of non-printable characters.”It cannot see the symbol (which is interpreted by the shell), but it can find out whether the output is going to a terminal.
In order to organize files nicely into the columns, ls
needs to know the width of the terminal. When the output device is not a terminal, it just doesn't know how to format its output.
Another nice consequence of this behavior is that you can do things like ls | wc -l
without worrying about multiple files on the same line. (You still have to worry about file names containing newlines, though.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With