When you pipe the output, ls acts differently.
This fact is hidden away in the info documentation:
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.
To prove it, try running
ls
and then
ls | less
Working on a little script the other day I had the need to determine if the input to the script was coming from a pipe or from the terminal. Seems like a simple enough thing to determine but nothing jumped immediately to mind and a quick internet search didn't help much either. After a bit of pondering I came up with two solutions: the stat command and using information from the proc file system.
R. Sałustowicz, M. Wiering, and J. Schmidhuber. Proceedings of the Seventh International Conference on
Artificial Neural Networks (ICANN'97), volume 1327 of Lecture Notes in Computer Science, page 769--774. Springer-Verlag, (1997)
R. Franke, F. Casella, M. Sielemann, K. Prölß, M. Otter, and M. Wetter. Proceedings of the 7th International Modelica Conference, volume 43 of Linköping Electronic Conference Proceedings, page 122--131. Linköping, Linköping University Electronic Press, Linköpings universitet, (2009)