Posso selezionare solo un risultato da un glob bash?


14

Sto cercando di scrivere uno script per il lavoro per automatizzare alcuni rapporti su un output. I file di registro sono (attualmente, saranno "standardizzati" in futuro) memorizzati in questo tipo di struttura del percorso:

/<root_path>/<process_one_path>/logs/<time_date_stamp>/<specific_log_file>

/<root_path>/<process_two_path>/logs/<different_time_date_stamp>/<specific_log_file>

Ogni parte del percorso è nota ad eccezione dei timestamp, che sono sempre gli ultimi nella cartella.

Se provo a utilizzare un carattere jolly al posto della data e ora, ottengo più risultati, ad esempio:

> ls /<root_path>/<process_two_path>/logs/* [tab]
20130102-175103
20130118-090859
20130305-213506

Voglio solo che restituisca l'ultimo, è possibile con Bash?

NB (non ho zsh, e per quanto possa sembrare bello, dubito che riusciremo mai a farlo funzionare)

Risposte:


9

Il seguente funziona in bash 4.2:

list=( /<root_path>/<process_two_path>/logs/* )
echo "${list[-1]}"

Se il tuo bash è una versione precedente:

list=( /<root_path>/<process_two_path>/logs/* )
echo "${list[${#list[@]}-1]}"

Funziona sicuramente sul mio computer di casa ma non posso garantire che funzionerà al lavoro?
Pureferret,

@Pureferret la parte che potrebbe non funzionare è l'indice di array negativo ( -1). Questo è stato aggiunto in bash 4.2. RHEL5 è probabilmente la più antica distribuzione supportata per le imprese mainstream disponibile e utilizza bash 4.2.20.
Patrick,

1
Le versioni precedenti di bashhave: "${list[@]: -1}"like in ksh93( come [-1]from zsh).
Stéphane Chazelas,

@Patrick - RHEL5 usa bash 3.2. RHEL 3 e 4 sono ancora supportati a vita estesa.
Giordania,

1
@Pureferret Puoi anche fare l'aritmetica con la lunghezza dell'array, vedi la mia modifica.
Gilles 'SO- smetti di essere malvagio' il

10

POSIXly:

 set -- /<root_path>/<process_two_path>/logs/*
 shift "$(($# - 1))"
 printf '%s\n' "$1"

Dal momento che menzioni zsh:

 print -r /<root_path>/<process_two_path>/logs/*([-1])

4

Usa il bash glob in un bash per loop. Come questo:

for filename in <logdir>/*; do :; done; echo "$filename"

Ciò dipende dal fatto che bash fa l'espansione glob in ordine alfabetico. Leggi il manuale di bash per maggiori informazioni. Si noti che questo dipende da LC_COLLATE . Ciò dipende anche dal fatto che la variabile filenamecontiene ancora l'ultimo valore dopo che il ciclo è terminato.

Se si desidera il nome file con il timestamp più vecchio, è possibile farlo in questo modo:

for filename in <logdir>/*; do echo "$filename"; break; done

1

-1 è l'impostazione predefinita nelle pipeline e l'output di ls dovrebbe già essere ordinato:

ls | tail -n1

Se altri cercavano come inserire il primo o l'ultimo risultato in modo interattivo, puoi associare menu-complete o menu-complete-backward in .inputrc:

"\e\t": menu-complete
"\e[Z": menu-complete-backward # shift-tab

Se show-all-if-ambiguous è abilitato, set completion-query-items 0rimuove il prompt quando ci sono 101 o più risultati e set page-completions offdisabilita il cercapersone.


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.