Elenca i file ordinati numericamente


123

Ho un sacco di file da log1a log164.

Sto cercando di ELENCO la directory (ordinata) in un terminale UNIX ma le funzioni di ordinamento forniscono solo il formato in questo modo:

home:logs Home$ ls -1 | sort
log1.gz
log10.gz
log100.gz
log101.gz
log102.gz
log103.gz
log104.gz
log105.gz
log106.gz
...etc

Quello che voglio è

home:logs Home$ ls -1 | sort
log1.gz
log2.gz
log3.gz
log4.gz
log5.gz
log6.gz
log7.gz
...{more here}
log99.gz
log100.gz
log101.gz
log102.gz
...etc

Qualche suggerimento su cosa potrei usare per fare questo?


8
Questa è assolutamente una domanda di programmazione, e non merita di essere migrata solo perché la risposta coinvolge il modesto linguaggio di programmazione della shell !!!
tchrist

Se si conosce in anticipo che stanno chiamati log1.gzattraverso log164.gz, allora che cosa è nemmeno necessario ls -1loro per?
Ruakh

1
@ruakh ls -1 mostra i risultati in una colonna anziché in tutta

3
@Rabiani: so cosa ls -1fa: elenca i nomi dei file. Dato che conoscevi già i nomi dei file, non ho capito a cosa ti servisse. Ma da quando hai accettato la risposta di Kevin, ora lo so: non ne hai avuto bisogno. Il che ha più senso. :-)
ruakh

Risposte:


40

bashLe parentesi graffe, {}le enumereranno in ordine:

for file in log{1..164}.gz; do
    process "$file"
done

267

Perché non utilizzare la lsfunzione integrata per questo caso particolare, vale a dire

-v natural sort of (version) numbers within text

Per esempio ls -1v log*


Soluzione fantastica, anche se vorrei che ci fosse una soluzione altrettanto semplice da utilizzare sort, nel caso in cui uno abbia una matrice di stringhe anziché una directory di file
Hubro

23
Su BSD / OSX questa opzione è un'altra cosa: -v - Force unedited printing of non-graphic characters.
Kenorb,

Sfortunatamente l'opzione -v non è disponibile su AIX (6.1)
bouvierr il

6
Questa dovrebbe essere la risposta migliore.
32r34wgf3e,

1
per MacOS questo funzionerà, non è stato possibile trovare un'opzione come menzionato, solols | sort -n
Ricky Levi,

47

Con GNU ls (es. Su Linux, Cygwin o altri sistemi su cui GNU l è installato in modo specifico):

ls -v

In zsh:

echo *(n)

In altre conchiglie:

echo log?.gz log??.gz log???.gz

Sostituisci echocon printf '%s\n'se vuoi che ciascun nome di file su una riga separata.

Se vuoi anche metadati di file ( ls -l) e non hai GNU ls, dovrai chiamare lsseparatamente per ogni nome di file o gruppo di nomi di file che vuoi vedere in ordine lessicografico.

ls -ld log?.gz; ls -ld log??.gz; ls -ld log???.gz

Per evitare queste difficoltà, utilizzare abbastanza zero iniziali nei nomi dei file in modo che l'ordinamento lessicografico sia a misura d'uomo ( log001.gz, ecc.).


29

Mentre la soluzione ls -1vè sicuramente la più bella in questo caso particolare, penso che sia bello averne una che sortfunzioni come nella domanda originale, poiché funziona anche quando il tuo input non proviene ls. In questo caso puoi usare:

ls -1 | sort -n -k1.4

L' -nopzione dice all'ordinamento di ordinare numericamente e -k 1.4imposta la chiave di ordinamento sul primo campo (che in questo caso è l'intero nome del file) a partire dal 4 ° carattere fino all'ultimo.


Nel mio caso, ls -1 | sort -n -k1.4non funziona. Fornisce quelli non ordinati all'inizio fino a 4 caratteri, quindi quelli ordinati dopo il 4 ° carattere. Ho usato ls -1 |sort | sort -n -k1.4invece e ha funzionato perfettamente.
Prabhu,

3
@Prabhu, invece, potresti farlo sort -k1.1,1.3 -k1.4n. sortle implementazioni non devono essere stabili, quindi il tuo approccio non funzionerà con tutte le implementazioni. Vedi anche l' -Vopzione di GNU e FreeBSD sort.
Stéphane Chazelas,

21

La GNU sort(come disponibile su Linux) ha una modalità di "ordinamento versione" che interpreta i numeri all'interno di non numeri proprio come chiedi:

Da man 1 sort:

    -V, --version-sort
           natural sort of (version) numbers within text

(Creazione di file di test vuoti da elencare
touch log1.gz log2.gz log3.gz log99.gz log100.gz log101.gz log102.gz:)

Il tuo esempio, aggiungendo l' -Vopzione (o --version-sort):

ls -1 log*.gz | sort -V
log1.gz
log2.gz
log3.gz
log99.gz
log100.gz
log101.gz
log102.gz


3

La mia versione di Solaris non supporta ls -v(grrr). E la soluzione di ordinamento fornita sopra 1) richiede la conoscenza della posizione delle cifre nel nome del file e 2) non gestisce cose come i numeri di versione in più parti.

L'approccio seguente è compatibile con Solaris, non richiede la conoscenza preliminare delle posizioni delle cifre e gestisce i numeri di versione con 2, 3 o 4 componenti (come: a-1.2, foo-5.6.7, bar_baz_9.10.11.12). Utilizza anche sort -fper piegare le lettere maiuscole e minuscole e gestisce correttamente le directory mescolate con i file:

ls -d | sort -f -t . -k 1,1 -k 2,2n -k 3,3n -k 4,4n

Si noti che questa versione limita il primo componente a una singola cifra.

Se il tuo sistema operativo di destinazione supporta ls -v, questa è chiaramente la soluzione migliore.


1

Soluzione Perl:

ls log*.gz | perl -ne 'sub getnum{ $_[0] =~ /log(\d+)\.gz/; $1 }; push @A, $_; END{ print sort { getnum $a <=> $b } @A}'

1
$ ls
log101.gz  log102.gz  log103.gz  log104.gz  log105.gz  log106.gz  log10.gz  log1.gz
$ ls | sort -t . -n -k1.4
log1.gz
log10.gz
log101.gz
log102.gz
log103.gz
log104.gz
log105.gz
log106.gz

1
Qui -t .è superfluo.
Stéphane Chazelas,

0

Questo ha funzionato per me.

Ho file 1.jpg 2.jpg ... 18.jpg

$ echo *.jpg | tr -s ' ' '\n' | sort -n

sortviene confuso con l' lsoutput a causa dei caratteri di colore non stampabili. Se provi questo:

ls -1 --color=none *.jpg | sort -n

funzionerà perfettamente.

sortpuò ignorare i caratteri non stampabili con l' -iopzione ma continua a non funzionare e non so perché.

Ma puoi sempre togliere il colore in questo modo e sortfunzionerà:

ls -1 --color=always *.jpg | sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[mGK]//g" | sort -n

Spero che un giorno sortavremo un'opzione per questo.

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.