Respuestas:
En bash o ksh, coloque los nombres de archivo en una matriz e itere sobre esa matriz en orden inverso.
files=(/var/logs/foo*.log)
for ((i=${#files[@]}-1; i>=0; i--)); do
bar "${files[$i]}"
done
El código anterior también funciona en zsh si la ksh_arraysopción está configurada (está en modo de emulación ksh). Hay un método más simple en zsh, que es invertir el orden de las coincidencias a través de un calificador global:
for f in /var/logs/foo*.log(On); do bar $f; done
POSIX no incluye matrices, por lo que si desea ser portátil, su única opción para almacenar directamente una matriz de cadenas son los parámetros posicionales.
set -- /var/logs/foo*.log
i=$#
while [ $i -gt 0 ]; do
eval "f=\${$i}"
bar "$f"
i=$((i-1))
done
iy f; simplemente realice un shift, use $1para su llamada bary pruebe [ -z $1 ]en su while.
[ -z $1 ]tampoco [ -z "$1" ]son pruebas útiles (¿qué pasa si el parámetro era *, o una cadena vacía?). Y en cualquier caso, no ayudan aquí: la pregunta es cómo hacer un bucle en el orden opuesto.
Intente esto, a menos que considere los saltos de línea como "personajes originales":
ls /var/logs/foo*.log | tac | while read f; do
bar "$f"
done
fen mi situación. Sin embargo, esta respuesta actúa más o menos como un reemplazo directo para la forlínea ordinaria .
Si alguien está tratando de descubrir cómo revertir la iteración sobre una lista de cadenas delimitadas por espacios, esto funciona:
reverse() {
tac <(echo "$@" | tr ' ' '\n') | tr '\n' ' '
}
list="a bb ccc"
for i in `reverse $list`; do
echo "$i"
done
> ccc
> bb
> a
taces parte de los coreutils de GNU. Pero su solución también es buena.
tac. Aunque por la cantidad de tacrespuestas sin respuesta aquí, supongo que quizás OSX no tiene tac. En cuyo caso, use alguna variante de la solución de @ arp; de todos modos, es más fácil de entender.
find /var/logs/ -name 'foo*.log' -print0 | tail -r | xargs -0 bar
Debe funcionar de la manera que desee (esto se probó en Mac OS X y tengo una advertencia a continuación ...).
Desde la página del manual para encontrar:
-print0
This primary always evaluates to true. It prints the pathname of the current file to standard output, followed by an ASCII NUL character (charac-
ter code 0).
Básicamente, está buscando los archivos que coinciden con su cadena + glob y termina cada uno con un carácter NUL. Si sus nombres de archivo contienen nuevas líneas u otros caracteres extraños, find debería manejar esto bien.
tail -r
toma la entrada estándar a través de la tubería y la invierte (tenga en cuenta que tail -rimprime toda la entrada en stdout, y no solo las últimas 10 líneas, que es el valor predeterminado estándar. man tailpara obtener más información).
Luego lo canalizamos a xargs -0:
-0 Change xargs to expect NUL (``\0'') characters as separators, instead of spaces and newlines. This is expected to be used in concert with the
-print0 function in find(1).
Aquí, xargs espera ver argumentos separados por el carácter NUL, desde el cual pasó findy revirtió tail.
Mi advertencia: he leído que tailno funciona bien con cadenas terminadas en nulo . Esto funcionó bien en Mac OS X, pero no puedo garantizar que ese sea el caso para todos los * nixes. Ve con cuidado.
También debo mencionar que GNU Parallel se usa a menudo como una xargsalternativa. También puedes comprobar eso.
Puede que me falte algo, por lo que otros deberían intervenir.
tail -r... ¿Estoy haciendo algo mal?
taccomo una alternativa, así que lo intentaría, en su lugar
tail -res específico de OSX e invierte la entrada delimitada por nueva línea, no la entrada delimitada por nulos. Su segunda solución no funciona en absoluto (está canalizando información ls, lo que no le importa); No hay una solución fácil que lo haga funcionar de manera confiable.
En su ejemplo, está recorriendo varios archivos, pero encontré esta pregunta debido a su título más general, que también podría abarcar la reproducción en bucle sobre una matriz o la inversión según cualquier número de órdenes.
Aquí se explica cómo hacerlo en Zsh:
Si está recorriendo los elementos en una matriz, use esta sintaxis ( fuente )
for f in ${(Oa)your_array}; do
...
done
Oinvierte el orden especificado en el siguiente indicador; aes el orden normal de la matriz.
Como dijo @Gilles, Onrevertirá el orden de sus archivos globales, por ejemplo, con my/file/glob/*(On). Eso es porque Ones " orden de nombre inverso ".
Banderas de clasificación Zsh:
a orden de la matrizL longitud del archivol número de enlacesm fecha de modificaciónn nombre^oorden inverso ( oes el orden normal)O orden inversoPara ver ejemplos, consulte https://github.com/grml/zsh-lovers/blob/master/zsh-lovers.1.txt y http://reasoniamhere.com/2014/01/11/outrageously-useful-tips- para-dominar-tu-z-shell /
Mac OSX no es compatible con el taccomando. La solución de @tcdyl funciona cuando se llama a un solo comando en un forbucle. Para todos los demás casos, la siguiente es la forma más sencilla de evitarlo.
Este enfoque no admite tener nuevas líneas en sus nombres de archivo. La razón subyacente es que tail -rordena su entrada delimitada por nuevas líneas.
for i in `ls -1 [filename pattern] | tail -r`; do [commands here]; done
Sin embargo, hay una manera de evitar la limitación de la nueva línea. Si sabe que sus nombres de archivo no contienen un determinado carácter (por ejemplo, '='), puede usar trpara reemplazar todas las líneas nuevas para convertirse en este carácter y luego ordenarlas. El resultado sería el siguiente:
for i in `find [directory] -name '[filename]' -print0 | tr '\n' '=' | tr '\0' '\n'
| tail -r | tr '\n' '\0' | tr '=' '\n' | xargs -0`; do [commands]; done
Nota: dependiendo de su versión de tr, es posible que no sea compatible '\0'con un personaje. Esto generalmente se puede solucionar cambiando la configuración regional a C (pero no recuerdo exactamente cómo, ya que después de arreglarlo una vez ahora funciona en mi computadora). Si recibe un mensaje de error y no puede encontrar la solución, publíquelo como comentario para que pueda ayudarlo a solucionarlo.
sort -rantes defor, o lávatels -r.