Subject: bug#25388: Bug in ls, kills existing scripts reading "ls" -1 as input

From: Eric Blake <[email-masked]>
Date: Mon, 9 Jan 2017 13:33:19 -0600

On 01/09/2017 01:00 PM, L A Walsh wrote:
> Paul Eggert wrote:
>> L A Walsh wrote:
>>>     Having 'ls' show different output through a pager than it
>>> does when scrolling off the screen is not a standard feature.
>>
>> Sure it is. 'ls' has done that since then 1980s. 'ls' shows
>> multicolumn output when the output is a tty, and single-column output
>> when piped into a pager.
> ----
> That would be really annoying if it were true.  It doesn't do that
> on any of my *nix terms.  When I put it through a pager I want it to page
> the output I just saw.  That's what it's for.

But that's EXACTLY what POSIX has specified, because it has been
existing practice for YEARS.

http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ls.html
"STDOUT
    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.
"

And POSIX merely codified existing practice (this is nothing new - it
has been this way since the 70's) - the earliest versions of ls used
isatty(), and implicitly turned on at least -q if stdout was a terminal
or -1 if it was not, which means that you have ALWAYS had different
behavior between 'ls' and 'ls | more', at least when ls is not some
alias that explicitly specifies other command line options to override
the defaults.

The GNU Coding Standards explicitly discourage NEW programs from
changing default behavior based solely on whether stdout is a tty or
not, but existing programs like ls are grandfathered in to have their
historical behavior, which predates the GNU Coding Standards.

> 
> I.e. using a pager, should not, by default, change the output
> of programs.  It's purpose is to moderate the output stream
> so a user can read what was output when they ran it without
> the pager.  Changing the output, by default, depending on
> pager usage defeats the primary purpose of pagers.

I agree that it is not nice to change output merely based on the type of
fd that stdout is, and GNU Coding Standards agrees in general.  But like
it or not, that's precisely what happens in ls due to
backwards-compatibility - using a pager through a pipeline changes
stdout from being a tty to instead being a pipeline, and therefore
changes default output of at least 'ls', and such change in behavior is
POSIX-compliant.

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org