is piped ls the same as ls -1?

ls returns output in several columns, whereas ls|cat returns byte-identical output with ls -1 for directories I’ve tried. Still I see ls -1 piped in answers, like ls -1|wc -l. Is there ever a reason to prefer ls -1? Why does ...|cat change the output of ls?

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

ls tests whether output is going to a terminal. If the output isn’t going to a terminal, then -1 is the default. (This can be overridden by one of the -C, -m, or -x options.)

Thus, when ls is used in a pipeline and you haven’t overridden it with another option, ls will use -1. You can rely on this because this behavior is required by POSIX

POSIX Specification

POSIX requires -1 as the default whenever output is not going to a terminal:

The POSIX spec:

The default format shall be to list one entry per line to standard
output; the exceptions are to terminals or when one of the -C, -m, or
-x options is specified. If the output is to a terminal, the format is implementation-defined.

Those three options which override the default single-column format are:

-C
Write multi-text-column output with entries sorted down the columns, according to the collating sequence. The number of text
columns and the column separator characters are unspecified, but
should be adapted to the nature of the output device. This option
disables long format output.

-m
Stream output format; list pathnames across the page, separated by a <comma> character followed by a <space> character. Use a
<newline> character as the list terminator and after the separator
sequence when there is not room on a line for the next list entry.
This option disables long format output.

-x
The same as -C, except that the multi-text-column output is produced with entries sorted across, rather than down, the columns.
This option disables long format output.

GNU Documentation

From GNU ls manual:

‘-1’
‘–format=single-column’
List one file per line. This is
the default for ls when standard output is not a terminal
. See also
the -b and -q options to suppress direct output of newline characters
within a file name. [Emphasis added]

Examples

Let’s create three files:

$ touch file{1..3}

When output goes to a terminal, GNU ls chooses to use a multi-column format:

$ ls
file1  file2  file3

When output goes to a pipeline, the POSIX spec requires that single-column is the default:

$ ls | cat
file1
file2
file3

The three exceptions which override the default single-column behavior are -m for comma-separated, -C for columns sorted down, and -x for columns sorted across:

$ ls -m | cat
file1, file2, file3
$ ls -C | cat
file1  file2  file3
$ ls -x | cat
file1  file2  file3

Method 2

  • Why does piping the standard output change the behavior of ls
    Because it was designed that way. 
    The POSIX Specification says:

    The default format shall be to list one entry per line to standard output;
    the exceptions are to terminals
    or when one of the -C, -m, or -x options is specified. 
    If the output is to a terminal, the format is implementation-defined.

    which is actually ambiguous about the default behavior
    (when not specified by an option like -l or -1)
    with output to a terminal, and the GNU Coreutils documentation says

    If standard output is a terminal,
    the output is in columns (sorted vertically)
    and control characters are output as question marks;
    otherwise, the output is listed one per line
    and control characters are output as-is.

    So you can see that output to a file will act the same as output to a pipe;
    that is, one entry per line, as if -1 had been specified.

  • Why was it designed that way? 
    It might not be possible to know for sure
    (unless somebody can find some design notes), but I guess:
    • When ls is writing to a terminal,
      it expects that a human being is looking at the output. 
      People will prefer to get information in the minimum necessary
      number of lines, so stuff doesn’t scroll of the screen.
    • When ls is writing to a pipe,
      it expects that another program is reading the output. 
      It’s much easier for a program to read data that’s one value per line
      than to have to try to parse columns (since filenames can contain spaces).
  • Is there ever a reason to prefer ls -1
    when you’re writing to a file or a pipe? 
    No.

Method 3

When piping ls, ls cannot determine how much columns the console actually has (independant of the right-side command). So ls just does that on its own choice, or, in other words, this behaviour is unstable and may change in future versions.

In contrast, ls -1 was created for the purpose of counting or scripting in general, so its behaviour is stable.


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x