How do I columnate any uncollumnated input like ls does?

ls is creating an optimized table with minimum width for each row, for example:


2  dsao  file with space  with
5  e     g                wsdl-rubo-6cb0f1a9086e80c
d  file   leading space

but if I feed output into column (for ex. each file on one line), it pads every row the same width, so it fits the screen width:

for i in *; do echo "$i"; done | column

2                               file with space                          
5                               g                                        
d                                leading space                           
dsao                            with                                     
e                               wsdl-rubo-6cb0f1a9086e80c                

(I use only the file list here to generate the same output as example, I am looking for such a solution to columnize other things in the end.)

How can I colunnize any output with a variable col-width?

  • Okay, an alternate reading of your request, if I understand your comments correctly, would be "columnate the input like column -c_n -x` does, but fit the output into as few screen columns as possible rather than filling out the specified width". Is this correct? – jthill Nov 21 '13 at 2:47
  • yes nearly: additionally there should be resulting as many columns as possible that fit into the screen. (like ls manages it). Maybe we find the solution, if we look into the sourcecode of the sourcecode of ls command in coreutils – rubo77 Nov 21 '13 at 3:43

Thanks @rubo77 for asking this, it's a great exercise. For me it was to off-by-one errors what English is Tough Stuff is to botched rhythm: it got fun, fast, even though the algorithm itself here is pretty simple.

[ final edit: moved to https://github.com/jthill/columnate/blob/master/columnate, bug fixed, row-major implemented. ]

  • also you should put this on github. If it is faster than the ls-algorythm, maybe you can create a faster ls-util? – rubo77 Nov 22 '13 at 8:27
  • @rubo77 You need to feed it the COLUMNS variable. see the 'test with' comment in the code. And that 10x-20x is the other way around, it's slower, mostly because it's awk vs C. – jthill Nov 22 '13 at 10:50
  • time ls | sort | columnate COLUMNS=$COLUMNS – jthill Nov 22 '13 at 11:38
  • You are a genius. This has to be published for every linux distribution – rubo77 Nov 22 '13 at 15:31
  • eh, thanks, really, but that's too strong. read the code, it's nearly brute-force – jthill Nov 22 '13 at 16:49

Something close to the output of ls:

for i in *; do echo -en "${i}\t"; done; echo
  • nice, it is only jumping in row, if the input lines are varying more than one tab in width. Is there a way to prevent a break of the output at the right window side? – rubo77 Nov 21 '13 at 9:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.