Могу ли я выбрать только один результат из bash glob?

14

Я пытаюсь написать скрипт для работы, чтобы автоматизировать некоторые отчеты о выходе. Файлы журнала (в настоящее время это «стандартизация» в будущем) хранятся в такой структуре путей:

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

Известна каждая часть пути, кроме меток даты и времени, которые всегда являются самыми последними в папке.

Если я попытаюсь использовать подстановочный знак вместо метки даты и времени, я получу несколько результатов, например:

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

Я только хочу вернуть последнюю версию, возможно ли это с Bash?

NB (у меня нет zsh, и как бы мило это не звучало, я сомневаюсь, что мы когда-нибудь получим его на работе)

Pureferret
источник

Ответы:

9

Следующие работы в Bash 4.2:

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

Если ваш bash - более старая версия:

list=( /<root_path>/<process_two_path>/logs/* )
echo "${list[${#list[@]}-1]}"
Патрик
источник
Это определенно работает на моем домашнем компьютере, но я не могу гарантировать, что он будет работать на работе?
Pureferret
@Pureferret часть, которая может не работать, является отрицательным индексом массива ( -1). Это было добавлено в Bash 4.2. RHEL5, вероятно, является самым старым поддерживаемым общедоступным корпоративным дистрибутивом и использует bash 4.2.20.
Патрик
Старые версии bashимеют: "${list[@]: -1}"как в ksh93( [-1]исходит от zsh).
Стефан Шазелас
@Patrick - RHEL5 использует bash 3.2. RHEL 3 и 4 все еще поддерживаются в течение продленного срока.
Иордания
1
@Pureferret Вы также можете сделать арифметику с длиной массива, см. Мое редактирование.
Жиль
10

POSIXly:

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

Поскольку вы упоминаете zsh:

 print -r /<root_path>/<process_two_path>/logs/*([-1])
Стефан Шазелас
источник
4

Используйте шар bash в цикле bash for. Нравится:

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

Это зависит от того, что bash выполняет расширение глобуса, отсортированное по алфавиту. Прочтите руководство по bash для получения дополнительной информации. Обратите внимание, что это зависит от LC_COLLATE . Это также зависит от того факта, что переменная по- filenameпрежнему содержит последнее значение после завершения цикла.

Если вам нужно имя файла с самой старой отметкой времени, вы можете сделать это следующим образом:

for filename in <logdir>/*; do echo "$filename"; break; done
lesmana
источник
0

-1 по умолчанию в конвейерах, и вывод ls уже должен быть отсортирован:

ls | tail -n1

Если другие искали, как вставить первый или последний результат в интерактивном режиме, вы можете связать menu-complete или menu-complete-backward в .inputrc:

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

Если функция show-all-if-ambiguous включена, set completion-query-items 0удаляет запрос, если имеется 101 или более результатов, и set page-completions offотключает пейджер.

LRI
источник