¿Puedo seleccionar solo un resultado de un bash glob?

14

Estoy tratando de escribir un script para el trabajo para automatizar algunos informes en una salida. Los archivos de registro se almacenan (actualmente, se está 'estandarizando' en el futuro) en este tipo de estructura de ruta:

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

Se conoce cada parte de la ruta, excepto las marcas de fecha y hora, que siempre son las últimas en la carpeta.

Si trato de usar un comodín en lugar de la marca de fecha y hora, obtengo múltiples resultados, por ejemplo:

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

Solo quiero que devuelva el último, ¿es esto posible con Bash?

NB (no tengo zsh, y por encantador que parezca, dudo que lo tengamos en el trabajo)

Pureferret
fuente

Respuestas:

9

Lo siguiente funciona en bash 4.2:

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

Si tu bash es una versión anterior:

list=( /<root_path>/<process_two_path>/logs/* )
echo "${list[${#list[@]}-1]}"
Patricio
fuente
Esto definitivamente funciona en la computadora de mi casa, pero ¿no puedo garantizar que funcione en el trabajo?
Pureferret 05 de
@Pureferret la parte que podría no funcionar es el índice de matriz negativo ( -1). Esto se agregó en bash 4.2. RHEL5 es probablemente la distribución empresarial mainstream compatible más antigua disponible y utiliza bash 4.2.20.
Patrick
1
Las versiones anteriores de bashhave: "${list[@]: -1}"like in ksh93( [-1]proviene de zsh).
Stéphane Chazelas
@Patrick: RHEL5 usa bash 3.2. RHEL 3 y 4 todavía son compatibles con una vida útil prolongada.
jordanm
1
@Pureferret También puedes hacer aritmética con la longitud de la matriz, mira mi edición.
Gilles 'SO- deja de ser malvado'
10

POSIXY:

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

Como mencionas zsh:

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

Usa el bash glob en un bash for loop. Me gusta esto:

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

Esto depende del hecho de que bash hace la expansión global clasificada alfabéticamente. Lea el manual de bash para más información. Tenga en cuenta que esto depende de LC_COLLATE . Esto también depende del hecho de que la variable filenametodavía contiene el último valor después de que el ciclo ha terminado.

Si desea el nombre de archivo con la marca de tiempo más antigua, puede hacerlo así:

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

-1 es el valor predeterminado en las canalizaciones, y la salida de ls ya debería estar ordenada:

ls | tail -n1

Si otros buscaban cómo insertar el primer o el último resultado de forma interactiva, puede vincular menu-complete o menu-complete-backward en .inputrc:

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

Si show-all-if-ambiguous está habilitado, set completion-query-items 0elimina la solicitud cuando hay 101 o más resultados y set page-completions offdeshabilita el buscapersonas.

Lri
fuente