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.
lsNo fallará.Respuestas:
Prueba esto:
Al pasar
xargsel-rindicador, solo se ejecutarábasenamesi lee al menos un elemento de la entrada estándar (head -1).head -1se 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 redirigirlsla 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_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.fuente
ls -rt GLOB 2>/dev/null | head -n1 | xargs -r basenamefunciona.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
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):Si no hay coincidencia, ese comando fallará y abortará el script. También puedes hacer:
En cuyo caso, la
first_file_namematriz 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:
newestPara usar esto correctamente para cumplir con el propósito de su solicitud:
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 renombrarseoldesty 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.
fuente
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ónlspara 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.