Come seleziono un campo / colonna dall'output di `ls -l`?


22

Il mio obiettivo è ingannevolmente semplice (almeno per me). Vorrei prendere l'output di ls -lo ls -lhe selezionare solo un campo.

Sto cercando che questo sia il più a prova di proiettile possibile, intendo dire che i nomi dei file possono avere un numero variabile di spazi, non tutto nel campo ha la stessa lunghezza, ecc.

Punti bonus per avere uno script che prenderà il nome del campo (o anche solo un numero di campo), e quindi restituirà il contenuto del campo.

Voglio girare

inserisci qui la descrizione dell'immagine

in:

inserisci qui la descrizione dell'immagine

Risposte:


41

Prova ls -l | awk '{print $7}'.

awk seleziona le colonne, quindi è perfetto per questa attività.


3
Come spiegato da @ormaaj: non fare affidamento sulla disponibilità di informazioni in luoghi specifici con ls. Il findcomando è estremamente utile.
Paddy Landau,

@PaddyLandau Come posso usare il comando find per stampare una dimensione del file in megabyte come posso fare con ls -l --block-size=M?
SurpriseDog

@Benjamin - Il lscomando non è standard POSIX, quindi uno script da cui dipende lspotrebbe rompersi su sistemi diversi o anche nel tempo. Vedi la risposta di @ormaaj in questa pagina per maggiori dettagli. Un modo per fare ciò che chiedi è con un loop Bash. Ecco un esempio for FILENAME in *; do FILESIZE=$(( $( stat --format=%s "${FILENAME}" ) / 1024 )); echo "${FILENAME}" ${FILESIZE}; done. Ovviamente, invece di echoutilizzare la tua elaborazione.
Paddy Landau,

@PaddyLandau Ho appena finito di inviare l'output del comando find a ... | xargs -d '\n' du -mcui funziona altrettanto bene.
Surprise

@Benjamin Potresti voler esaminare l' -execopzione di find.
Paddy Landau,

17

Non analizzare mai . Usa GNU find. Oppure, se la portabilità non è importante, stat(1).

find . -maxdepth 1 -printf '%Td\n'

Per leggere dati diversi dagli elenchi di nomi di file riga per riga e suddividere in campi, vedere: BashFAQ / 001

Non ci sono metodi per leggere in modo affidabile un elenco di nomi di file delimitato da nuova riga che ha senso nella maggior parte dei casi.


1

Puoi recuperare la colonna specifica nella shell come:

ls -al | while read perm bsize user group size month day time file; do echo $day; done

o awkcome mostrato in @Corey risposta , cut -c44-45potrebbe funzionare anche dopo la regolazione (poiché lsè fisso colonne), o quant'altro, ma il problema principale è che non sarà affidabile e proiettile (ad esempio su Unix può essere $6, non $7, e cambia a seconda degli argomenti) rendendolo non intuitivo, pertanto non è consigliabile analizzare il lscomando .

La cosa migliore è usare diversi comandi disponibili come findo stat, che possono fornire opzioni pertinenti per formattare l'output di cui hai bisogno. Per esempio:

$ stat -c "%x %n" *
2016-04-10 04:53:07.000000000 +0100 001.txt
2016-04-10 05:08:42.000000000 +0100 7c1c.txt

Per restituire la colonna dei soli giorni di modifiche, prova questo esempio:

stat -c "%x" * | while read ymd; do date --date="$ymd" "+%d"; done

Vale la pena notare che GNU statpotrebbe avere diverse opzioni rispetto a BSD stat, quindi non sarà ancora a prova di proiettile su diversi sistemi operativi.


1
+1 per menzionare che ls non deve essere analizzato e per l'uso di stat. datetuttavia è impostato in modo errato. Dovresti aggiungere --date=$ymd, dal momento che dateda solo stamperà il giorno corrente, ma lo scopo qui è convertire il formato della data del file
Sergiy Kolodyazhnyy

Il ls -la | cut -c32-33comando in totale onestà è completamente inaffidabile, non solo a causa delle possibili insidie ​​con i nomi dei file, ma semplicemente perché dipende dalla lunghezza dei nomi utente e dalle dimensioni dei file. Il stat -c "%x" *.*comando sembra ok, ma usando *.*lo stai limitando solo ai nomi di file che contengono un punto. Immagino che l'intenzione fosse quella di catturare anche file nascosti; in questo caso si dovrebbe abilitare il globbing per dotfile in anticipo e utilizzare *al posto di *.*: shopt -s dotglob; stat -c "%x" * | [...].
kos

Ah e anche quello che ha detto Serg, dovresti aggiungere --date="$ymd"al datecomando, altrimenti stamperà il giorno corrente del mese.
kos

Grazie per i commenti Ho affrontato i problemi e fornito un esempio iniziale migliore.
Kenorb,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.