Puis-je sélectionner un seul résultat d'un glob bash?

14

J'essaie d'écrire un script pour le travail afin d'automatiser certains rapports sur une sortie. Les fichiers journaux sont (actuellement, ils sont en train d'être «standardisés» à l'avenir) stockés dans ce type de structure de chemin:

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

Chaque partie du chemin est connue à l'exception des horodatages, qui sont toujours les plus récents du dossier.

Si j'essaie d'utiliser un caractère générique à la place de l'horodatage, j'obtiens plusieurs résultats, par exemple:

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

Je veux seulement qu'il retourne le dernier, est-ce possible avec Bash?

NB (je n'ai pas de zsh, et aussi beau que cela puisse paraître, je doute que nous l'aurons jamais au travail)

Pureferret
la source

Réponses:

9

Les travaux suivants dans bash 4.2:

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

Si votre bash est une ancienne version:

list=( /<root_path>/<process_two_path>/logs/* )
echo "${list[${#list[@]}-1]}"
Patrick
la source
Cela fonctionne certainement sur mon ordinateur personnel, mais je ne peux pas garantir que cela fonctionnera au travail?
Pureferret
@Pureferret la partie qui pourrait ne pas fonctionner est l'index de tableau négatif ( -1). Cela a été ajouté dans bash 4.2. RHEL5 est probablement la distribution d'entreprise la plus ancienne prise en charge disponible et utilise bash 4.2.20.
Patrick
1
Les anciennes versions de bashhave: "${list[@]: -1}"like in ksh93( [-1]vient de zsh).
Stéphane Chazelas
@Patrick - RHEL5 utilise bash 3.2. RHEL 3 et 4 sont toujours pris en charge sous une durée de vie prolongée.
jordanm
1
@Pureferret Vous pouvez également faire de l'arithmétique avec la longueur du tableau, voir ma modification.
Gilles 'SO- arrête d'être méchant'
10

POSIX:

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

Puisque vous mentionnez zsh:

 print -r /<root_path>/<process_two_path>/logs/*([-1])
Stéphane Chazelas
la source
4

Utilisez le bash glob dans une boucle bash for. Comme ça:

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

Cela dépend du fait que bash effectue une expansion globale triée par ordre alphabétique. Lisez le manuel bash pour plus d'informations. Notez que cela dépend de LC_COLLATE . Cela dépend également du fait que la variable filenamecontient toujours la dernière valeur après la fin de la boucle.

Si vous voulez le nom de fichier avec le plus ancien horodatage, vous pouvez le faire comme ceci:

for filename in <logdir>/*; do echo "$filename"; break; done
lesmana
la source
1

-1 est la valeur par défaut dans les pipelines, et la sortie ls doit déjà être triée:

ls | tail -n1

Si d'autres cherchaient comment insérer le premier ou le dernier résultat de manière interactive, vous pouvez lier menu-complete ou menu-complete-backward dans .inputrc:

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

Si show-all-if-ambiguous est activé, set completion-query-items 0supprime l'invite lorsqu'il y a 101 résultats ou plus et set page-completions offdésactive le pager.

Lri
la source