Czy mogę wybrać tylko jeden wynik z bash glob?

14

Próbuję napisać skrypt do pracy, aby zautomatyzować raportowanie danych wyjściowych. Pliki dziennika są (obecnie są „standaryzowane” w przyszłości) przechowywane w takiej strukturze ścieżki:

/<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>

Każda część ścieżki jest znana z wyjątkiem znaczników daty i godziny, które zawsze są najnowsze w folderze.

Jeśli spróbuję użyć dzikiej karty zamiast znacznika daty, otrzymam wiele wyników, np .:

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

Chcę tylko, aby zwrócił najnowszą wersję, czy jest to możliwe dzięki Bash?

NB (nie mam zsh, i choć brzmi to tak uroczo, wątpię, czy kiedykolwiek dostaniemy to w pracy)

Pureferret
źródło

Odpowiedzi:

9

Poniższe działa w bash 4.2:

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

Jeśli twoja wersja jest starszą wersją:

list=( /<root_path>/<process_two_path>/logs/* )
echo "${list[${#list[@]}-1]}"
Patrick
źródło
To zdecydowanie działa na moim komputerze domowym, ale nie mogę zagwarantować, że zadziała w pracy?
Pureferret,
@Pureferret częścią, która może nie działać, jest indeks tablicy ujemnej ( -1). Zostało to dodane w bash 4.2. RHEL5 jest prawdopodobnie najstarszą dostępną dystrybucją głównego nurtu dla przedsiębiorstw i wykorzystuje bash 4.2.20.
Patrick,
1
Starsze wersje bashhave: "${list[@]: -1}"like in ksh93( [-1]pochodzi z zsh).
Stéphane Chazelas,
@Patrick - RHEL5 używa bash 3.2. RHEL 3 i 4 nadal obsługiwane w ramach przedłużonej żywotności.
jordanm
1
@Pureferret Możesz także wykonywać arytmetykę z długością tablicy, zobacz moją edycję.
Gilles 'SO - przestań być zły'
10

POSIXly:

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

Ponieważ wspomniałeś zsh:

 print -r /<root_path>/<process_two_path>/logs/*([-1])
Stéphane Chazelas
źródło
4

Użyj bash glob w bash for loop. Lubię to:

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

Zależy to od tego, że bash dokonuje globalnej ekspansji posortowanej alfabetycznie. Przeczytaj instrukcję bash, aby uzyskać więcej informacji. Zauważ, że zależy to od LC_COLLATE . Zależy to również od faktu, że zmienna filenamenadal zawiera ostatnią wartość po zakończeniu pętli.

Jeśli chcesz mieć nazwę pliku z najstarszym znacznikiem czasu, możesz to zrobić w następujący sposób:

for filename in <logdir>/*; do echo "$filename"; break; done
lesmana
źródło
1

-1 jest wartością domyślną w potokach, a dane wyjściowe ls powinny być już posortowane:

ls | tail -n1

Jeśli inni szukali sposobu interaktywnego wstawiania pierwszego lub ostatniego wyniku, możesz powiązać menu-complete lub menu-complete-backward w .inputrc:

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

Jeśli opcja „pokaż wszystko jeśli niejednoznaczne” jest włączona, set completion-query-items 0usuwa monit, gdy jest 101 lub więcej wyników i set page-completions offwyłącza pager.

Lri
źródło