Convertir la sortie de ls en csv

Comment pourrais-je convertir:

$ find . -ls > /tmp/files.txt 

Ce qui me donne quelque chose comme:

 908715 40 -rwxrwxr-x 1 david staff 16542 Nov 15 14:12 ./dump_info.py 908723 0 drwxr-xr-x 2 david staff 68 Nov 20 17:35 ./metadata 

Dans une sortie csv? Cela ressemblerait à:

 908715,40,-rwxrwxr-x,1,david,staff,16542,Nov 15 14:12,./dump_info.py 908723,0,drwxr-xr-x,2,david,staff,68,Nov 20 17:35,./metadata 

Voici un exemple de titre avec des espaces dans le nom du fichier:

 652640,80,-rw-rw-r--,1,david,staff,40036,Nov,6,15:32,./v_all_titles/V Catalog Report 11.5.xlsx 

C’est un peu long de taper sur la ligne de commande, mais cela préserve correctement les espaces dans le nom du fichier (et le cite aussi!)

 find . -ls | python -c ' import sys for line in sys.stdin: r = line.ssortingp("\n").split(None, 10) fn = r.pop() print ",".join(r) + ",\"" + fn.replace("\"", "\"\"") + "\"" ' 

Si vous ne vous souciez pas des espaces dans la date:

 $ find . -ls | tr -s ' ' , 

Si vous vous souciez de ces espaces:

 $ find . -ls | awk '{printf( "%s,%s,%s,%s,%s,%s,%s,%s %s %s,%s\n", $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11 )}' 

Aucun de ces éléments ne fonctionnera si vos noms de fichiers contiennent des espaces. En tant que hack pour traiter les espaces du nom de fichier, vous pouvez essayer:

  ... | sed 's/,/ /8g' 

pour se débarrasser de toutes les sauf les 8 premières virgules (en supposant que votre sed supporte l’option non standard de 8g comme le fait gnou sed). Bien sûr, cela ne concerne pas les virgules dans le nom du fichier.

Et encore une autre variante. Voir la section “-printf format” dans la page de manuel de find à personnaliser.

 $ find . -type f -fprintf /tmp/files.txt "%i,%b,%M,%n,%u,%g,%s,%CY-%Cm-%Cd %CT,%p\n" 

Exemple de sortie:

 $ less /tmp/files.txt 3414558,40,-rw-rw-r--,1,webwurst,webwurst,16542,2014-09-18 15:54:36.9232917780,./dump_info.py 3414559,8,-rw-rw-r--,1,webwurst,webwurst,68,2014-09-18 15:54:51.1752922580,./metadata 

Voici un script python que j’ai rédigé …

 #!/opt/app/python/bin/python # Convert ls output to clean csv Paolo Villaflores 2015-03-16 # # Sample usage: ls -l | ls2csv.py # # Features: # accepts -d argument to change dates to yyyy-mm-dd_hhmm format # input is via stdin # separate file/directory field # handle -dils type input (find -ls) versus -l # handle space in filename, by applying quotes around filename # handle date - format into something excel can handle correctly, whether it is from current year or not. # adds a header # handle symlinks - type l import sys from datetime import datetime b0=True def is_f(s): if s == '-': return 'f' return s for line in sys.stdin: if len(line) < 40: continue if b0: b1=line[0] in ['-', 'd', 'c', 'l'] # c is for devices eg /devices/pseudo/pts@0:5, l is for symbolic link b0=False if b1: # true when shorter ls -l style 8/9 columns. 9 for symlink cols=7 print "d,perms,#links,owner,group,size,modtime,name,symlink" else: cols=9 print "inode,bsize,d,perms,#links,owner,group,size,modtime,name,symlink" r = line.strip("\n").split(None, cols+1) if len(r) < cols+1: continue if r[cols-7][0] == 'c': continue # ignore c records: devices fn = r.pop() if b1: c = '' else: c = ",".join(r[0:2]) + "," z = 0 z = r[cols].find(':') if z < 0: d = r[cols - 1] + "/" + r[cols - 2] + "/" + r[cols] else: n = str(datetime.now() ) d = '' # handle the case where the timestamp has no year field tm=datetime.strptime(r[cols-2]+ " " + r[cols-1]+ " " + n[:4] +" " + r[cols], "%b %d %Y %H:%M") if (tm-datetime.now()).days > 0: d = r[cols - 1] + "/" + r[cols - 2] + "/" + str((datetime.now().year-1)) + " " + r[cols] tm=datetime.strptime(r[cols-2]+ " " + r[cols-1]+ " " + str(int(n[:4])-1) +" " + r[cols], "%b %d %Y %H:%M") else: d = r[cols - 1] + "/" + r[cols - 2] + "/" + " ".join([n[:4], r[cols] ] ) if len(sys.argv) > 1 and sys.argv[1] == '-d': d=tm.strftime("%Y-%m-%d_%H%M") y = fn.find(">") symlink='' if y > 0: symlink = ',\"' + fn[y+2:] + '"' fn = fn[:y-2] if fn.find( " ") <0: if fn.find('"') <0: fn2=fn else: fn2="'" + fn + "'" else: fn2="'" + fn + "'" print c+ is_f(r[cols-7][0]) + ",\"" + r[cols-7][1:] + "\"," + ",".join( r[cols-6:cols-2]) + "," + d + "," + fn2 + symlink 

cela devrait faire le travail

  find . -ls|awk 'BEGIN{OFS=","}$1=$1'