GNU/Linux >> Linux Esercitazione >  >> Linux

Il carattere jolly Bash Star * produce sempre un elenco ordinato (crescente)?

Ho una directory piena di file con nomi come logXX dove XX è un numero esadecimale maiuscolo di due caratteri, riempito con zero, come:

log00
log01
log02
...
log0A
log0B
log0C
...
log4E
log4F
log50
...

Generalmente ci saranno meno di 20 o 30 file in totale. La data e l'ora sul mio particolare sistema non sono qualcosa su cui si può fare affidamento (un sistema integrato senza fonti di tempo NTP o GPS affidabili). Tuttavia, i nomi dei file aumenteranno in modo affidabile come mostrato sopra.

Desidero grep attraverso tutti i file per la singola voce di registro più recente di un certo tipo, speravo di cat i file insieme come...

cat /tmp/logs/log* | grep 'WARNING 07 -' | tail -n1

Tuttavia mi è venuto in mente che diverse versioni di bash o sh o zsh ecc. potrebbero avere idee diverse su come il * è ampliato.

La man bash la pagina non dice se l'espansione di * sarebbe un elenco alfabetico decisamente crescente di nomi di file corrispondenti. Sembra aumentare ogni volta che l'ho provato su tutti i sistemi che ho a mia disposizione, ma è un comportamento DEFINITO o è solo specifico dell'implementazione?

In altre parole posso assolutamente fare affidamento su cat /tmp/logs/log* per concatenare tutti i miei file di registro insieme in ordine alfabetico?

Risposta accettata:

In tutte le shell, i glob sono ordinati per impostazione predefinita. Erano già del /etc/glob aiutante chiamato dalla shell di Ken Thompson per espandere i glob nella prima versione di Unix all'inizio degli anni '70 (e che diede il nome ai glob).

Per sh , POSIX richiede che vengano ordinati tramite strcoll() , ovvero utilizzando l'ordinamento nella locale dell'utente, come per ls anche se alcuni lo fanno ancora tramite strcmp() , che si basa solo su valori di byte.

$ dash -c 'echo *'
Log01B log-0D log00 log01 log02 log0A log0B log0C log4E log4F log50 log① log② lóg01
$ bash -c 'echo *'
log① log② log00 log01 lóg01 Log01B log02 log0A log0B log0C log-0D log4E log4F log50
$ zsh -c 'echo *'
log① log② log00 log01 lóg01 Log01B log02 log0A log0B log0C log-0D log4E log4F log50
$ ls
log②  log①  log00  log01  lóg01  Log01B  log02  log0A  log0B  log0C  log-0D  log4E  log4F  log50
$ ls | sort
log②
log①
log00
log01
lóg01
Log01B
log02
log0A
log0B
log0C
log-0D
log4E
log4F
log50

Potresti notare sopra che per quelle shell che eseguono l'ordinamento in base alla locale, qui su un sistema GNU con un en_GB.UTF-8 locale, il - nei nomi dei file viene ignorato per l'ordinamento (la maggior parte dei caratteri di punteggiatura lo farebbe). Il ó viene ordinato in un modo più previsto (almeno per gli inglesi) e il caso viene ignorato (tranne quando si tratta di decidere le cravatte).

Tuttavia, noterai alcune incongruenze per log① log②. Questo perché l'ordine di ordinamento di ① e ② non è definito nelle localizzazioni GNU (attualmente; si spera che un giorno verrà risolto). Ordinano allo stesso modo, quindi ottieni risultati casuali.

Correlati:Processo discendenti?

La modifica della lingua influirà sull'ordinamento. Puoi impostare la locale su C per ottenere un strcmp() -like sort:

$ bash -c 'echo *'
log① log② log00 log01 lóg01 Log01B log02 log0.2 log0A log0B log0C log-0D log4E log4F log50
$ bash -c 'LC_ALL=C; echo *'
Log01B log-0D log0.2 log00 log01 log02 log0A log0B log0C log4E log4F log50 log① log② lóg01

Si noti che alcune impostazioni locali possono causare confusione anche per le stringhe all-alnum ASCII. Come quelli cechi (almeno su sistemi GNU) dove ch è un elemento di confronto che ordina dopo h :

$ LC_ALL=cs_CZ.UTF-8 bash -c 'echo *'
log0Ah log0Bh log0Dh log0Ch

Oppure, come sottolineato da @ninjalj, ancora più strani nelle località ungheresi:

$ LC_ALL=hu_HU.UTF-8 bash -c 'echo *'
logX LOGx LOGX logZ LOGz LOGZ logY LOGY LOGy

In zsh , puoi scegliere l'ordinamento con i qualificatori glob. Ad esempio:

echo *(om) # to sort by modification time
echo *(oL) # to sort by size
echo *(On) # for a *reverse* sort by name
echo *(o+myfunction) # sort using a user-defined function
echo *(N)  # to NOT sort
echo *(n)  # sort by name, but numerically, and so on.

L'ordinamento numerico di echo *(n) può anche essere abilitato globalmente con il numericglobsort opzione:

$ zsh -c 'echo *'
log① log② log00 log01 lóg01 Log01B log02 log0.2 log0A log0B log0C log-0D log4E log4F log50
$ zsh -o numericglobsort -c 'echo *'
log① log② log00 lóg01 Log01B log0.2 log0A log0B log0C log01 log02 log-0D log4E log4F log50

Se tu (come lo ero io) sei confuso da quell'ordine in quel particolare caso (qui usando la mia lingua britannica), vedi qui per i dettagli.


Linux
  1. Il Bash '?

  2. Perché il file di traduzione Bash non contiene tutti i testi di errore?

  3. In uno script Bash Come funziona il comando Continua con i loop incorporati?

  4. Perché la Regex in Bash funziona solo se è una variabile e non direttamente??

  5. Come elencare la dimensione di ogni file e directory e ordinare per dimensione decrescente in Bash?

L'elenco delle scorciatoie da tastiera utili di Bash

Personalizzazione della shell Bash

Bash For Loop – La guida più pratica

Come personalizzare il completamento automatico di Bash per elencare i file in un'altra directory?

Ottenere cicli di cpu utilizzando RDTSC:perché il valore di RDTSC aumenta sempre?

Come funziona il pattern <( cmd ) in bash?