15

How can the output of ls -l be modified to separate fields using tabs instead of spaces? I want to paste the output into a spreadsheet; the padding with a variable number of spaces makes it difficult to do so. To illustrate:

drwxr-xr-x  2 root root     4096 Sep 26 11:43 wpa_supplicant
-rw-r-----  1 root dialout    66 Sep 26 11:43 wvdial.conf
drwxr-xr-x  9 root root     4096 Oct  8 08:21 X11
drwxr-xr-x 12 root root     4096 Feb 18 23:31 xdg
drwxr-xr-x  2 root root     4096 Jan 31 06:11 xml
drwxr-xr-x  2 root root     4096 Nov 22 07:26 xul-ext
-rw-r--r--  1 root root      349 Jan 13  2012 zsh_command_not_found

In the excerpt from ls -l /etc shown above, rows 1, 2 and 3 have a single digit in column 2 whereas row 4 has two. That means the alignment is achieved by using two spaces for separating columns 1 and 2 in rows 1-3, but just one space in row 4.

4 Answers4

8

Try:

ls -l | awk -v OFS="\t" '$1=$1'

Or, if your filenames have spaces:

ls -l | awk '{print $1,"\t",$2,"\t",$3,"\t",$4,"\t",$5,"\t",$6,"\t",$7,"\t",$8,"\t",$9,$10,$11,$12,$13,$14,$15;}'
philshem
  • 2,093
  • Unfortunately this does not work correctly for filenames that contain spaces. It replaces them with tabs as well. While this is simpler and runs faster than green7's script based solution, this will produce incorrect output a large amount of the time, and has no advantages over Aditya's method. Can this be modified so that spaces are no longer interpreted as input delimeters, after the 9th column? – Eliah Kagan Mar 26 '13 at 16:29
  • @psny18 The updated way is even more badly broken. It cuts off everything but the first word of each filename. Simply writing $9 does not change the fact that you have awk always interpreting spaces as indicating a break between columns. $9 captures only the first word in that position, and since the other words are considered separate, higher-numbered columns, they are never printed at all. – Eliah Kagan Mar 26 '13 at 16:45
  • That's a pity that filenames aren't treated as one column even if they have spaces in them. –  Mar 26 '13 at 17:22
  • @EliahKagan, how do you figure out that "this is simpler and runs faster" than the script-based solution? I get the simpler part, but how about "faster"? Did you use something like "time"? –  Mar 26 '13 at 17:24
  • @vasa1: green's method loops over all the files and spits the output one-by-one (one can see with naked eye). However, psny18's solution spits the output in one go. Try the solution, you would understand why it is faster :-) – Aditya Mar 26 '13 at 17:28
  • @vasa1 I ran them both multiple times, though admittedly on a small number of folders and only on one system. I this command appeared to complete immediately, whereas with the script on the same directories, it often takes a couple seconds to complete, and I can see the entries being written down the page (as opposed to bam! and I see all the output at once). Unfortunately, unless this can be modified to give correct output, or unless someone has a situation where they only need to perform this action on files guaranteed not to contain spaces, it probably doesn't matter that it's faster. – Eliah Kagan Mar 26 '13 at 17:29
  • Okay, I thought you used something like "time" to get values. I tried using "time" for something else but there was quite some variation between retries. –  Mar 26 '13 at 17:32
  • OK see update. Now it can handle 4 or 5 spaces in the file name. – philshem Mar 26 '13 at 17:45
3

I've made a shell script for the same. It takes care of the cases when the filenames have spaces or any other special characters.

#! /bin/bash

SAVEIFS=$IFS
IFS=$(echo -en "\n\b")
for file in $(ls)
do
    stat --printf="%A\t%h\t%U\t%G\t%s\t" $file
    mod_epoch=$(stat --format="%Y" $file)
    mod_month=$(date -d @$mod_epoch +"%b")
    mod_day=$(date -d @$mod_epoch +"%d")
    mod_time=$(date -d @$mod_epoch +"%H:%M")
    printf "%s\t%s\t%s\t%s\n" $mod_month $mod_day $mod_time $file
done
IFS=$SAVEIFS
  • Save it to a file, say ls_tab.sh
  • Make it executable:
chmod +x ls_tab.sh
  • Run it:
./ls_tab.sh

Note: This can be done by parsing the output of ls, however the reason why it should not be done is given here.

green
  • 14,306
  • 1
    If the goal is to know what ls says, parsing its output is fine. That is rarely the goal. Arguably it is here. I think the method you've used is quite good (any method will produce undesired results given some set of needs)! However, arguably parsing ls might be better. Consider the case of a filename that actually has a tab character in it. ls -l replaces the tab with a ? character. Your script preserves the tab character, which will create extra columns if its output is interpreted as tab-delimeted and used to create a spreadsheet. It degrades badly if a filename has a newline. – Eliah Kagan Mar 26 '13 at 14:37
  • 1
    True. But normally files do not have \n or \t in their names. If they do, then parsing the output of ls with simple bash commands will be more complex, but can be achieved. I can update the answer, if the OP wants to handle such cases. – green Mar 26 '13 at 16:17
  • This works for me and long filenames with spaces in them display properly. My usage is fairly simple and I hope not to deal with files with \n and \t in their names. –  Mar 26 '13 at 17:17
  • 1
    Perfect. For Windows speadsheet use printf "%s\t%s\t%s\t%s\r\n" $mod_month $mod_day $mod_time $file and to redirect the ouptut the file as ./ls_tab.sh > listing.txt. – Fedir RYKHTIK Jun 10 '13 at 09:23
1

We do not even need to convert the output as Tab Delimited. Space between columns is just fine enough.

Run your ls -l command in terminal as you normally do and copy the contents you wish to be pasted in a Spreadsheet.

terminal command

Next, open your Spreadsheet program (LibreOffice Calc in my case) and press Ctrl + V to paste the contents of your clipboard.

The Text Import Wizard would pop up. Make sure you put a checkmark beside Space and press Ok. You can watch the preview in the lower pane.

Libo Text Import

Aditya
  • 13,416
  • 3
    This won't work when filenames have spaces – green Mar 26 '13 at 14:24
  • @green7: Ah.. Didn't realize that! :-) – Aditya Mar 26 '13 at 14:30
  • Not just the filenames but also the number of characters in columns. Padding there and elsewhere causes problems if "space" is chosen as the delimiter. I'll edit the question to illustrate that. –  Mar 26 '13 at 15:50
0

python is good for this:

# python
import os

os.system( 'ls -lR --time-style=full-iso /home/jw > ls_dump.txt')

folder = ''

for line in open('ls_dump.txt', 'r'):

    inrec = line.split()

    if inrec == []:
        continue

    if inrec[0].startswith('total'):
        continue

    if inrec[0].endswith(':'):
        folder = inrec[0].replace(':','')
        continue

    outline = folder + '\t' + '\t'.join(inrec[0:8]) +'\t'+ ' '.join(inrec[8:]) 

    print( outline )
guntbert
  • 13,134
JWest
  • 1