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.