is piped ls the same as ls -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

  • 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.

Tags:

Shell

Ls