How come the ls command prints in multiple columns on tty but only one column everywhere else

lsshellunix

Even after using Unix-like OSes for a couple years, this behaviour still baffles me.

When I use the ls command in a directory that has lots of files, the output is usually nicely formatted into multiple columns. Here's an example:

$ ls
a.txt  C.txt  f.txt  H.txt  k.txt  M.txt  p.txt  R.txt  u.txt  W.txt  z.txt
A.txt  d.txt  F.txt  i.txt  K.txt  n.txt  P.txt  s.txt  U.txt  x.txt  Z.txt
b.txt  D.txt  g.txt  I.txt  l.txt  N.txt  q.txt  S.txt  v.txt  X.txt
B.txt  e.txt  G.txt  j.txt  L.txt  o.txt  Q.txt  t.txt  V.txt  y.txt
c.txt  E.txt  h.txt  J.txt  m.txt  O.txt  r.txt  T.txt  w.txt  Y.txt

However, if I try to redirect the output to a file, or pipe it to another command, only a single column appears in the output. Using the same example directory as above, here's what I get when I pipe ls to wc:

$ ls | wc
     52      52     312

In other words, wc thinks there are 52 lines, even though the output to the terminal has only 5.

I haven't observed this behaviour in any other command. Would you like to explain this to me?

Best Answer

It is simply detecting that it's output is a terminal device and formatting output so it looks better on it. You can print out the same formatted ls output to a file or pipe with option -C.

How to detect output is a terminal: https://stackoverflow.com/questions/1061575/detect-in-c-if-outputting-to-a-terminal