2009-09-19 8 views
12

Come faccio a ottenere awk per generare $ 9 $ 10 $ 11 ecc. Perché alcuni dei miei file contengono degli spazi.

ls -l | grep ^- | awk '{print $9}' 

risposta

28

Una soluzione migliore: non tentare di analizzare l'output di ls in primo luogo.

Il wiki ufficiale del canale irc.freenode.org #bash ha una spiegazione del motivo per cui questa è una cattiva idea, e ciò che si alternano approcci si può prendere invece: http://mywiki.wooledge.org/ParsingLs

Uso di trovare, stat e simili gli strumenti forniranno le funzionalità che stai cercando senza le trappole (non tutte sono ovvie, alcune si verificano solo quando si passa a piattaforme con implementazioni di ls diverse).

Per il tuo esempio specifico, suppongo che tu stia cercando di trovare solo i file (e non le directory) nella tua directory corrente; la tua attuale implementazione usando ls -l è buggata, in quanto esclude i file che hanno permessi + t o setuid. Il modo giusto per implementare questo sarebbe il seguente:

find . -maxdepth 1 -type f -printf '%f\n' 
+2

Considerare l'uso di \ 0 al posto di \ n se si sta alimentando l'output in un altro comando come 'grep -z' o' xargs -0'. Questo fa '-printf' funziona come' -print0'. –

+0

Come posso usare questo, ma filtro per estensione, ad esempio .txt? – inukaze

+0

@inukaze, inserisci '-name '* .txt'' prima di' -printf' –

1

C'è probabilmente un approccio migliore che coinvolge combinando i campi in qualche modo, ma:

 
$ echo 1 2 3 4 5 6 7 8 9 10 11 12 13 14... | awk '{for (i = 9 ; i <= NF ; i++) printf "%s ", $i}' 
9 10 11 12 13 14... 

Utilizzando printf "%s " $i stamperà il campo i-esimo con uno spazio dopo di esso, invece di un ritorno a capo. Il ciclo for dice semplicemente di passare dal campo 9 all'ultimo campo.

+0

questo fallirà quando c'è un doppio spazio –

1
echo 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 | awk 'BEGIN {OFS=ORS=""} ; {for (i=9;i<NF;i++) print $i " "; print $NF "\n"}' 
1

Se ancora insistere sulla ls -l invece di trovare o di altri strumenti, ecco la mia soluzione. Non è abbastanza e distruttivo:

  1. Destroy $ 1 .. $ 8 con impostandole a "" tramite un ciclo for
  2. che lascia un po 'di spazi precedenti $ 9, rimuoverli con il comando sub()
  3. Stampa restante

    ls -l | awk '{for (i = 1; i < 9; i ++) $ i = ""; sub (/^* /, ""); print} '

+0

È necessario prestare maggiore attenzione se è stato configurato 'ls' per mostrare i collegamenti simbolici (con un' ->/path/to/file 'alla fine); spogliarlo con 'sed'. –

1

Solo per il completamento. Esso può essere fatto anche con sed:

# just an exercise in regex matching ... 
ls -l | sed -E -e 1d -e /^[^-]/d -e 's/^([^ ]+ +){8}//' 
+0

@mikk Puoi spiegare il tuo comando? Penso che '-e/^ [^ -]/d' stia eliminando i collegamenti simbolici e' -e 's/^ ([^] + +) {8} //' 'sta stampando la nona colonna che non parte con uno spazio, ma cosa fa '-e 1d'? – Dannid

+0

@Dannid, mi sembra che stia cancellando la prima riga. Citando le specifiche POSIX per spiegare il perché: Se viene specificata una qualsiasi delle opzioni '-l',' -g', '-n',' -o' o '-s', ogni elenco di file all'interno della directory deve essere preceduto da una riga di stato che indica il numero di blocchi del file system occupati dai file nella directory in unità da 512 byte, arrotondati al numero integrale successivo di unità, se necessario. Nell'impostazione locale POSIX, il formato deve essere: '" total% u \ n ", ' –

1

Una soluzione è quella di codificare & decodificare lo spazio con una parola o un carattere utilizzando sed:

ls -l | grep ^- | sed s/\ /{space}/ | awk '{print $9}' | sed s/{space}/\/

Questo sostituirà tutti gli spazi in una linea con {space} prima di passarlo a awk. Dopo che la linea è passata a awk, sostituiamo {space} con spazio.

find come indicato da altri è una soluzione molto migliore. Ma se davvero devi usare awk, puoi provare questo.

1
ls -l | grep ^- | awk -v x=9 '{print $x}' 

Io lo uso per ottenere i nomi di file di una directory senza incidenti.Ho notato la soluzione di ricerca che va bene e dandy se non sei sicuro dei tipi di file, se sai che quello che stai guardando ls -l funziona bene, anche in ordine alfabetico per impostazione predefinita.

Problemi correlati