
INPUT_FILE=`ls -rt $MY_DIR/FILE.*.xml | head -1 | xargs basename`
Quería ejecutar el segundo comando ( head -1
) solo si el primer comando tiene éxito. ¿Cómo mejoro este comando?
Respuesta1
Prueba esto:
INPUT_FILE=`ls -rt "$MY_DIR"/FILE.*.xml | head -1 | xargs -r basename`
Pasar xargs
la -r
bandera hará que solo se ejecute 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 redirigir ls
la secuencia stderr de /dev/null
.
INPUT_FILE=`ls -rt "$MY_DIR"/FILE.*.xml 2> /dev/null | head -1 | xargs -r basename`
También tenga en cuenta que agregué comillas alrededor $MY_DIR
. De esa forma, 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 comillas invertidas. También deberías considerar cambiar el estilo de tus variables. En general, debes evitar el uso de nombres de variables completamente en mayúsculas en los scripts. Ese estilo generalmente está reservado para variables ambientales y reservadas.
input_file=$(ls -rt "$my_dir"/FILE.*.xml 2> /dev/null | head -1 | xargs -r basename)
Respuesta2
En una tubería, todos los comandos se inician y ejecutan simultáneamente, no uno tras otro. Entonces necesitas 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 los archivos no contienen caracteres de nueva línea. Usarlo xargs
también significaría problemas con caracteres en blanco, comillas simples y dobles y barras invertidas. Dejar las variables sin comillas significaría problemas con los espacios, tabulaciones y caracteres comodín. Olvidarlo --
significaría problemas con los nombres de archivos que comienzan con -
.
Para obtener el nombre base del archivo más antiguo zsh
sin ninguna de esas restricciones de 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 ninguna coincidencia, ese comando fallará y cancelará el script. También puedes hacer:
first_file_name=($MY_DIR/FILE.*.xml(NOm[1]:t))
En cuyo caso la first_file_name
matriz contendrá 1 elemento si hay una coincidencia o 0 si no. Luego puedes hacer:
if (($#first_file_name)); then
printf 'Match: %s\n' $first_file_name
else
echo >&2 No match
fi
Respuesta3
Busque el último archivo modificado en un directorio:
latest() {
local file path=${1:-.} ext=${2-} latest
for file in "${path%/}"/*"$ext"; do
[[ $file -nt $latest ]] && latest=$file
done
[[ $latest ]] && printf '%s\n' "$latest"
}
Uso:latest [directory/path/ [.extension]]
En lugar de llamar a basename
, utilice la expansión de parámetros.
in_file=$(latest in/my/dir .xml)
base_fn=${in_file##*/} base_fn=${base_fn%.*}
En un directorio con estos contenidos:
foo.xml bar.xml baz.xml newest.xml
El contenido de la variable base_fn sería:newest
Para utilizar 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" >&2
fi
EDITAR: al revisar la pregunta, me di cuenta de que el ls
comando en cuestión busca elmás antiguoarchivo en un directorio. Se podría cambiar el nombre de esta misma función oldest
y, [[ $file -ot $oldest ]] && oldest=$file
en su lugar, lograr el mismo efecto. disculpas por cualquier confusión.
Lo importante a tener en cuenta es que usted, bajo ninguna circunstancia en la humanidad, debe analizar la salida de ls. nunca.
Respuesta4
Creo que la mejor opción aquí es:
ls -rf $MY_DIR/FILE.*.xml
if [ $? -eq 0 ]; then
INPUT_FILE=`ls -rt $MY_DIR/FILE.*.xml|head -1|xargs basename `
else
echo "Error!"
fi
si no hay ningún archivo, entonces el código de retorno de ls es 2, pero si encuentra algún archivo será 0.