En Bash, me gustaría crear una función que devuelva el nombre de archivo del archivo más nuevo que coincida con un patrón determinado. Por ejemplo, tengo un directorio de archivos como:
Directory/
a1.1_5_1
a1.2_1_4
b2.1_0
b2.2_3_4
b2.3_2_0
Quiero el archivo más nuevo que comienza con 'b2'. ¿Cómo hago esto en bash? Necesito tener esto en mi ~/.bash_profile
guión.
Respuestas:
El
ls
comando tiene un parámetro-t
para ordenar por tiempo. Luego puedes tomar el primero (el más nuevo) conhead -1
.Pero cuidado: ¿por qué no deberías analizar la salida de ls?
Mi opinión personal: el análisis
ls
solo es peligroso cuando los nombres de archivo pueden contener caracteres divertidos como espacios o líneas nuevas. Si puede garantizar que los nombres de archivo no contendrán caracteres divertidos, entonces el análisisls
es bastante seguro.Si está desarrollando un script que está destinado a ser ejecutado por muchas personas en muchos sistemas en muchas situaciones diferentes, le recomiendo no analizar
ls
.Aquí se explica cómo hacerlo "correctamente": ¿Cómo puedo encontrar el archivo más reciente (más nuevo, más antiguo, más antiguo) en un directorio?
fuente
ls
,printf "%s\n" b2* | head -1
lo hará por usted.b2.10_5_2
mata esta solución.La combinación de
find
yls
funciona bien paraLa solución:
Vamos a desglosarlo:
Con
find
podemos hacer coincidir todos los archivos interesantes como este:luego usando
-print0
podemos pasar todos los nombres de archivos de forma segura a lals
siguiente:find
Aquí se pueden agregar parámetros y patrones de búsqueda adicionalesls -t
clasificará los archivos por hora de modificación (la más nueva primero) e imprimirá uno en una línea. Puede usar-c
para ordenar por hora de creación. Nota : esto se romperá con los nombres de archivo que contienen nuevas líneas.Finalmente
head -1
nos obtiene el primer archivo en la lista ordenada.Nota:
xargs
use límites del sistema para el tamaño de la lista de argumentos. Si este tamaño excede,xargs
llamaráls
varias veces. Esto interrumpirá la clasificación y probablemente también la salida final. correrpara verificar los límites de tu sistema.
Nota 2: utilícela
find . -maxdepth 1 -name "my-pattern" -print0
si no desea buscar archivos a través de subcarpetas.Nota 3: Como lo señaló @starfry: el
-r
argumentoxargs
es para evitar la llamada dels -1 -t
, si el archivo no coincidefind
. Gracias por la sugerencia.fuente
find . -name "my-pattern" ... -print0
me dafind: paths must precede expression: `...'
...
significa "más parámetros". Solo omítelo, si no lo necesitas.-r
a la línea de comando xargs que le dice a xargs que no ejecute su línea de comando si no recibe nada en su entrada estándar.-r
a la respuesta.Esta es una posible implementación de la función Bash requerida:
Utiliza solo los componentes internos de Bash y debe manejar archivos cuyos nombres contengan nuevas líneas u otros caracteres inusuales.
fuente
nullglob_shopt=$(shopt -p nullglob)
y luego$nullglob
volver a ponerlonullglob
como estaba antes.$()
o backticks) porque es lento, particularmente bajo Cygwin, incluso cuando el comando solo usa incorporados. Además, el contexto de subshell en el que se ejecutan los comandos a veces puede hacer que se comporten de manera inesperada. También trato de evitar almacenar comandos en variables (comonullglob_shopt
) porque pueden ocurrir cosas muy malas si obtiene el valor incorrecto de la variable.cat
!'. Incluso si esto requiere más trabajo, tiene el beneficio de mostrarle conceptos a las personas. Tener un +1!Los nombres de archivo inusuales (como un archivo que contenga el
\n
carácter válido pueden causar estragos en este tipo de análisis). Aquí hay una manera de hacerlo en Perl:Esa es una transformación Schwartziana usada allí.
fuente
Puede usar
stat
con un archivo glob y decorate-sort-undecorate con el tiempo de archivo agregado en el frente:fuente
stat
, si recuerdo sus opciones correctamente. Para obtener resultados similares en otras plataformas, puede usarstat -c $'%Y\t%n' b2* | sort -rn | head -n1 | cut -f2-
Encantamiento de la función de magia oscura para aquellos que desean la
find ... xargs ... head ...
solución anterior, pero en forma de función fácil de usar para que no tenga que pensar:Huellas dactilares:
Cual es:
El nombre de archivo con la marca de tiempo modificada más antigua del archivo en el directorio dado que coincide con el patrón dado.
fuente
Usa el comando find.
Suponiendo que está usando Bash 4.2+, use
-printf '%T+ %p\n'
para el valor de marca de tiempo del archivo.Ejemplo:
Para obtener una secuencia de comandos más útil, consulte la secuencia de comandos find-latest aquí: https://github.com/l3x/helpers
fuente
Hay una forma mucho más eficiente de lograr esto. Considere el siguiente comando:
Este comando encuentra el último archivo producido exactamente hace un minuto con la búsqueda con comodines en "b2 *". Si desea archivos de los últimos dos días, será mejor que use el siguiente comando:
Los "." representa el directorio actual. Espero que esto ayude.
fuente