Canalice la salida de un comando si tiene éxito

Canalice la salida de un comando si tiene éxito
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 xargsla -rbandera hará que solo se ejecute 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 redirigir lsla 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_DIRcontiene 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 xargstambié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 zshsin 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_namematriz 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 lscomando en cuestión busca elmás antiguoarchivo en un directorio. Se podría cambiar el nombre de esta misma función oldesty, [[ $file -ot $oldest ]] && oldest=$fileen 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.

información relacionada