Cómo verificar si existe un archivo en un script de shell

176

Me gustaría escribir un script de shell que verifique si un determinado archivo archived_sensor_data.jsonexiste y, de ser así, lo elimina. Siguiendo http://www.cyberciti.biz/tips/find-out-if-file-exists-with-conditional-expressions.html , he intentado lo siguiente:

[-e archived_sensor_data.json] && rm archived_sensor_data.json

Sin embargo, esto arroja un error

[-e: command not found

cuando trato de ejecutar el test_controllerscript resultante usando el ./test_controllercomando ¿Qué tiene de malo el código?

Kurt Peek
fuente
2
Debe establecer uno o más espacios en blanco entre el corchete de apertura "[" y la opción "-e" igual que entre el nombre de archivo y el corchete de cierre "]"
Konstantin Yaniv

Respuestas:

351

Te falta un espacio requerido entre el soporte y -e:

#!/bin/bash
if [ -e x.txt ]
then
    echo "ok"
else
    echo "nok"
fi
chris01
fuente
12
Finalmente añadí dos espacios en blanco, uno después del corchete de apertura y uno antes de que el uno de cierre: [ -e archived_sensor_data.json ] && rm archived_sensor_data.json. El guión parece funcionar ahora.
Kurt Peek
3
Esto también funciona utilizando if [ -e "$1" ](argumento de entrada de nombre de archivo).
Edward
2
La principal diferencia aquí es el hecho de que está utilizando secuencias de comandos "bash" en lugar de secuencias de comandos "shell". Observe que la primera línea que agregó fue #! / Bin / bash, por lo que le está diciendo a la máquina que use "bash" en lugar de sh. Porque sh no reconoce ese argumento "-e"
Nick Cuevas
29

Aquí hay un método alternativo que usa ls:

(ls x.txt && echo yes) || echo no

Si desea ocultar cualquier salida de lsmodo que solo vea sí o no, redirija stdouty stderra /dev/null:

(ls x.txt >> /dev/null 2>&1 && echo yes) || echo no
Philip Kirkbride
fuente
1
Este código significa: "si lstiene éxito, existe dicho archivo, de lo contrario, no hay ninguno". Si lsfalla, no significa que falta el archivo. Podría ser algún otro error. Por ejemplo, cree un archivo en el directorio propiedad de root e intente hacerlo lscon un usuario normal. Fallará Permission denied, lo que no es equivalente a que el archivo no exista.
Tigran
9

El telón de fondo de mi recomendación de solución es la historia de un amigo que, bien entrada la segunda semana de su primer trabajo, limpió la mitad de un servidor de compilación. Entonces, la tarea básica es averiguar si existe un archivo y, de ser así, eliminarlo. Pero hay algunos rápidos traicioneros en este río:

  • Todo es un archivo

  • Los scripts tienen poder real solo si resuelven tareas generales

  • Para ser general, utilizamos variables

  • A menudo usamos -f force en los scripts para evitar la intervención manual.

  • Y también love -r recursive para asegurarnos de que creamos, copiamos y destruimos de manera oportuna.

Considere el siguiente escenario:

Tenemos el archivo que queremos eliminar: filesexists.json

Este nombre de archivo se almacena en una variable

<host>:~/Documents/thisfolderexists filevariable="filesexists.json"

También tenemos una variable de ruta para hacer las cosas realmente flexibles

<host>:~/Documents/thisfolderexists pathtofile=".."

<host>:~/Documents/thisfolderexists ls $pathtofile

filesexists.json  history20170728  SE-Data-API.pem  thisfolderexists

Entonces, veamos si -ehace lo que se supone que debe hacer. ¿Existen los archivos?

<host>:~/Documents/thisfolderexists [ -e $pathtofile/$filevariable ]; echo $?

0

Lo hace. Magia.

Sin embargo, qué sucedería si la variable del archivo se evaluara accidentalmente como nuffin '

<host>:~/Documents/thisfolderexists filevariable=""

<host>:~/Documents/thisfolderexists [ -e $pathtofile/$filevariable ]; echo $?

0

¿Qué? Se supone que debe regresar con un error ... Y este es el comienzo de la historia de cómo esa carpeta completa se eliminó por accidente

Una alternativa podría ser probar específicamente lo que entendemos como un 'archivo'

<host>:~/Documents/thisfolderexists filevariable="filesexists.json"

<host>:~/Documents/thisfolderexists test -f $pathtofile/$filevariable; echo $?

0

Entonces el archivo existe ...

<host>:~/Documents/thisfolderexists filevariable=""

<host>:~/Documents/thisfolderexists test -f $pathtofile/$filevariable; echo $?

1

Así que este no es un archivo y tal vez, no queremos eliminar todo ese directorio

man test tiene lo siguiente que decir:

-b FILE

       FILE exists and is block special

-c FILE

       FILE exists and is character special

-d FILE

       FILE exists and is a directory

-e FILE

       FILE exists

-f FILE

       FILE exists and is a regular file

...

-h FILE

       FILE exists and is a symbolic link (same as -L)
Zurdo G Balogh
fuente
4

Internamente, el comando rm debe probar la existencia del archivo de todos modos,
entonces , ¿por qué agregar otra prueba? Solo emitir

rm filename

y desaparecerá después de eso, ya sea que esté allí o no.
Use rm -f si no desea ningún mensaje sobre archivos inexistentes.

Si necesita tomar alguna medida si el archivo NO existe, debe probarlo usted mismo. Según su código de ejemplo, este no es el caso en esta instancia.

TG
fuente
1
En realidad, esta es una respuesta bastante válida para el comando rm. Para otros comandos, sugiero probar con -e.
warhansen el
Excepto que no es lo que hace la pregunta.
Crayones
1
Es en gran medida lo que la pregunta pregunta, si lees toda la pregunta, incluida la parte "... y (si es así) ... la elimina".
TG
1

Si está utilizando un NFS, "prueba" es una mejor solución, porque puede agregarle un tiempo de espera, en caso de que su NFS esté inactivo:

time timeout 3 test -f 
/nfs/my_nfs_is_currently_down
real    0m3.004s <<== timeout is taken into account
user    0m0.001s
sys     0m0.004s
echo $?
124   <= 124 means the timeout has been reached

Una construcción "[-e my_file]" se congelará hasta que el NFS vuelva a funcionar:

if [ -e /nfs/my_nfs_is_currently_down ]; then echo "ok" else echo "ko" ; fi

<no answer from the system, my session is "frozen">
FCA69
fuente
testy [son sinónimos También puede usar timeoutcon [, y testtambién se congela si NFS se bloquea.
ese otro chico