How come the ls command prints in multiple columns on tty but only one column everywhere else?
Solution 1
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
Solution 2
When the output of a program provides a list of some sort, and you redirect the output of the program to a file, or pipe it to another program, typically it is for the purpose of the second program to read the original program output (or the file), in a loop, 1 line at a time.
In this sort of case, it is almost always more convenient for each line that is read to contain one item (1 filename), or 1 "record" of information about a single item, rather than a number of different items that have to be split apart.
This is especially the case for filenames that can contain spaces because spaces are also the delimiter that separates each item (filename).
For example ...
First, I create some files:
% touch "300"
% cp "300" "301"
% cp "300" "302 304"
% cp "300" "303 305"
% cp "300" "306"
% cp "300" "307"
% cp "300" "308"
% cp "300" "309"
% cp "300" "310 312"
% cp "300" "311 313"
% cp "300" "314 316"
% cp "300" "315 317"
% cp "300" "318"
% cp "300" "319"
% cp "300" "320 322"
% cp "300" "321 323"
% cp "300" "324"
% cp "300" "325"
% cp "300" "bar bin"
% cp "300" "baz boo"
% cp "300" "def"
% cp "300" "etc"
% cp "300" "foo mos"
%
Now, I get a "long" listing of the files I created:
% ls -l
-rw-r--r-- 1 username username 0 Nov 28 01:51 300
-rw-r--r-- 1 username username 0 Nov 28 01:51 301
-rw-r--r-- 1 username username 0 Nov 28 01:51 302 304
-rw-r--r-- 1 username username 0 Nov 28 01:51 303 305
-rw-r--r-- 1 username username 0 Nov 28 01:51 306
-rw-r--r-- 1 username username 0 Nov 28 01:51 307
-rw-r--r-- 1 username username 0 Nov 28 01:51 308
-rw-r--r-- 1 username username 0 Nov 28 01:51 309
-rw-r--r-- 1 username username 0 Nov 28 01:51 310 312
-rw-r--r-- 1 username username 0 Nov 28 01:51 311 313
-rw-r--r-- 1 username username 0 Nov 28 01:51 314 316
-rw-r--r-- 1 username username 0 Nov 28 01:51 315 317
-rw-r--r-- 1 username username 0 Nov 28 01:51 318
-rw-r--r-- 1 username username 0 Nov 28 01:51 319
-rw-r--r-- 1 username username 0 Nov 28 01:51 320 322
-rw-r--r-- 1 username username 0 Nov 28 01:51 321 323
-rw-r--r-- 1 username username 0 Nov 28 01:51 324
-rw-r--r-- 1 username username 0 Nov 28 01:51 325
-rw-r--r-- 1 username username 0 Nov 28 01:51 bar bin
-rw-r--r-- 1 username username 0 Nov 28 01:51 baz boo
-rw-r--r-- 1 username username 0 Nov 28 01:51 def
-rw-r--r-- 1 username username 0 Nov 28 01:51 etc
-rw-r--r-- 1 username username 0 Nov 28 01:51 foo mos
%
OK, so that is fairly obvious what the filenames are.
Now, I get a listing of the files by columns:
% ls
300 302 304 306 308 310 312 314 316 318 320 322 324 bar bin def foo mos
301 303 305 307 309 311 313 315 317 319 321 323 325 baz boo etc
%
As you can see, a program reading the output (and even a human observer) would not be able to pick out the correct names of the files and would probably think this is a long list of 3 character filenames.
If we pipe the output of ls into more, we get:
% ls | more
300
301
302 304
303 305
306
307
308
309
310 312
311 313
314 316
315 317
318
319
320 322
321 323
324
325
bar bin
baz boo
def
etc
foo mos
%
While not very pretty, it is now much easier to pick the correct filenames because each filename is on its own line.
Related videos on Youtube

ᔕᖺᘎᕊ
I'm in my second year of uni in the UK. I'm interested in html, php, javascript, jquery, node.js, python, css, and flutter. I LOVE Chuck!! :D If you need to get in touch with me, see my website for more details. Userscripts I've made some userscripts for the Stack Exchange sites you may be interested in: My SOOF userscript, now Stack Overflow Extras, has a bunch of optional features you can add to 'enhance' SE (examples of these features are: pre-defined edit reasons; side-by-side post editing; highlight answerer's names in comments, and so on) My SE WYSIWYG Editor userscript adds a WYSIWYG (What You See Is What You Get) Editor to Stack Exchange - definitely worth a try! :) My Freehand Circles Drawing Tool userscript allows you to draw directly onto images you see on SE sites - you can change the brush colour and width to draw anything you might want - it's great fun, useful and easy to use :) My Self Destructing Comments userscript allows you to set a date at which a comment you wrote should be deleted - useful for those 'comment cleanup', 'thanks', or 'welcome' comments. My SE Desktop Notifications userscript shows desktop notifications whenever there is new activity on a question open in a new tab - useful for keeping track of questions without having to scroll through the answers to see if there is a new edit, or comment, or score change :) See many more at my Stack Apps profile :) ǝɯɐuɹǝsn ʎɯ ɹoɟ ɯoɔ˙sloqɯʎsɟ˙ʍʍʍ oʇ sʞuɐɥʇ
Updated on September 18, 2022Comments
-
ᔕᖺᘎᕊ 4 months
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?
-
Admin about 10 yearsOh is that it? I see. Thanks for satisfying my curiosity. :)
-
piokuc about 10 yearsNo problem. If your curiosity is satisfied then I think you can kindly close the question.