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 es exitoso. ¿Cómo mejoro este comando?
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 es exitoso. ¿Cómo mejoro este comando?
Respuestas:
Prueba esto:
INPUT_FILE=`ls -rt "$MY_DIR"/FILE.*.xml | head -1 | xargs -r basename`
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 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 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.
input_file=$(ls -rt "$my_dir"/FILE.*.xml 2> /dev/null | head -1 | xargs -r basename)
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.
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 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):
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_name
matriz 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 >&2 No match
fi
Encuentre 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
, use 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 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" >&2
fi
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 renombrarse oldest
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.
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ón ls
para obtener el mismo comportamiento allí).
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 archivo, el código de retorno de ls es 2 pero si encuentra algún archivo será 0.
ls
No fallará.