También tenga en cuenta que agregué comillas alrededor $MY_DIR. De esa manera, el comando no fallará si $MY_DIRcontiene espacios.
Si está utilizando un shell moderno como bash, debe usar un $( )shell de captura en lugar de backticks. También debe considerar cambiar el estilo de sus variables. En general, debe evitar el uso de nombres de variables en mayúsculas en los scripts. Ese estilo está generalmente reservado para variables reservadas y ambientales.
input_file=$(ls -rt "$my_dir"/FILE.*.xml 2>/dev/null | head -1| xargs -r basename)
En realidad: ls -rt GLOB 2>/dev/null | head -n1 | xargs -r basenamefunciona.
Mel Boyce
@MelBoyce: He agregado eso a mi respuesta. Gracias.
ls es una herramienta para mirar interactivamente la información del archivo. Su salida está formateada para humanos y causará errores en los scripts. Usa globos o encuentra en su lugar. Comprenda por qué: mywiki.wooledge.org/ParsingLs
cinelli
@cinelli: Eso es verdad. Estaba respondiendo la pregunta.
9
En una tubería, todos los comandos se inician y se ejecutan simultáneamente, no uno tras otro. Por lo tanto, debe almacenar la salida en algún lugar.
if ls_output=$(ls -rtd --"$MY_DIR"/FILE.*.xml);then
first_file=$(printf '%s\n'"$ls_output"| head -n 1)
first_file_name=$(basename --"$first_file")fi
Tenga en cuenta que se supone que los nombres de archivo no contienen caracteres de nueva línea. El uso xargstambién significaría problemas con caracteres en blanco, comillas simples y dobles y barras invertidas. Dejar variables sin comillas significaría problemas con el espacio, la tabulación y los caracteres comodín. Olvidar --significaría problemas con los nombres de archivo que comienzan con -.
Para obtener el nombre base del archivo más antiguo zshsin ninguna de esas restricciones en los caracteres (también evita el problema del tamaño limitado de los argumentos de un comando):
first_file_name=($MY_DIR/FILE.*.xml(Om[1]:t))
Si no hay coincidencia, ese comando fallará y abortará el script. También puedes hacer:
first_file_name=($MY_DIR/FILE.*.xml(NOm[1]:t))
En cuyo caso, la first_file_namematriz contendrá 1 elemento si hay una coincidencia o 0 si no. Entonces puedes hacer:
if(($#first_file_name)); then
printf 'Match: %s\n' $first_file_name
else
echo >&2No match
fi
Para usar esto correctamente para cumplir con el propósito de su solicitud:
check_dir=/path/to/check
check_ext=.xml
if in_file=$(latest "$check_dir""$check_ext");then
base_fn=${in_file##*/} base_fn=${base_fn%.*}else
printf '%s\n'"No file found in $check_dir">&2fi
EDITAR: al revisar la pregunta, me di cuenta de que el lscomando en cuestión está buscando el archivo más antiguo en un directorio. esta misma función podría renombrarse oldesty tener [[ $file -ot $oldest ]] && oldest=$fileque lograr el mismo efecto. disculpas por cualquier confusión.
Lo importante a tener en cuenta es que absolutamente, bajo ninguna circunstancia en la humanidad, no debe analizar la salida de ls. Nunca.
Tenga en cuenta que, a diferencia de los lsenfoques basados en, si hay enlaces simbólicos, se considerará el tiempo de modificación del objetivo de los enlaces simbólicos (agregue la -Lopción lspara obtener el mismo comportamiento allí).
En lugar de comparar $?contra 0, usted puede hacer esto: if ls -rf $MY_DIR/FILE.*.xml ; then.
Además, puede redirigir la salida del primer comando a /dev/null. ls -rf $MY_DIR/FILE.*.xml &> /dev/null. De esa manera, el usuario no verá la salida adicional.
ls
No fallará.Respuestas:
Prueba esto:
Al pasar
xargs
el-r
indicador, solo se ejecutarábasename
si lee al menos un elemento de la entrada estándar (head -1
).head -1
se ejecutará pero no verá ni capturará ningún resultado.Además, si no desea que el usuario vea ningún resultado de error
ls
, puede redirigirls
la secuencia stderr de/dev/null
.También tenga en cuenta que agregué comillas alrededor
$MY_DIR
. De esa manera, el comando no fallará si$MY_DIR
contiene espacios.Si está utilizando un shell moderno como bash, debe usar un
$( )
shell de captura en lugar de backticks. También debe considerar cambiar el estilo de sus variables. En general, debe evitar el uso de nombres de variables en mayúsculas en los scripts. Ese estilo está generalmente reservado para variables reservadas y ambientales.fuente
ls -rt GLOB 2>/dev/null | head -n1 | xargs -r basename
funciona.En una tubería, todos los comandos se inician y se ejecutan simultáneamente, no uno tras otro. Por lo tanto, debe almacenar la salida en algún lugar.
Tenga en cuenta que se supone que los nombres de archivo no contienen caracteres de nueva línea. El uso
xargs
también significaría problemas con caracteres en blanco, comillas simples y dobles y barras invertidas. Dejar variables sin comillas significaría problemas con el espacio, la tabulación y los caracteres comodín. Olvidar--
significaría problemas con los nombres de archivo que comienzan con-
.Para obtener el nombre base del archivo más antiguo
zsh
sin ninguna de esas restricciones en los caracteres (también evita el problema del tamaño limitado de los argumentos de un comando):Si no hay coincidencia, ese comando fallará y abortará el script. También puedes hacer:
En cuyo caso, la
first_file_name
matriz contendrá 1 elemento si hay una coincidencia o 0 si no. Entonces puedes hacer:fuente
Encuentre el último archivo modificado en un directorio:
Uso:
latest [directory/path/ [.extension]]
En lugar de llamar a
basename
, use la expansión de parámetros.En un directorio con estos contenidos:
El contenido de la variable base_fn sería:
newest
Para usar esto correctamente para cumplir con el propósito de su solicitud:
EDITAR: al revisar la pregunta, me di cuenta de que el
ls
comando en cuestión está buscando el archivo más antiguo en un directorio. esta misma función podría renombrarseoldest
y tener[[ $file -ot $oldest ]] && oldest=$file
que lograr el mismo efecto. disculpas por cualquier confusión.Lo importante a tener en cuenta es que absolutamente, bajo ninguna circunstancia en la humanidad, no debe analizar la salida de ls. Nunca.
fuente
ls
enfoques basados en, si hay enlaces simbólicos, se considerará el tiempo de modificación del objetivo de los enlaces simbólicos (agregue la-L
opciónls
para obtener el mismo comportamiento allí).Creo que la mejor opción aquí es:
si no hay archivo, el código de retorno de ls es 2 pero si encuentra algún archivo será 0.
fuente
$?
contra0
, usted puede hacer esto:if ls -rf $MY_DIR/FILE.*.xml ; then
./dev/null
.ls -rf $MY_DIR/FILE.*.xml &> /dev/null
. De esa manera, el usuario no verá la salida adicional.