Chuleta 06 ¿El fichero existe?

Cuando empiezas a tirar código Shell con cierta soltura empiezas a meter validaciones digamos que básicas, ¿existe el fichero de configuración de este proceso?, ¿y la ruta del fichero de log que voy a grabar?, ¿el fichero de datos a procesar existe? ¿lo puedo leer? ¿y además tiene datos o está vacio?

A todas estas preguntas y a bastantes más podemos dar respuesta con un simple IF y la correspondiente evaluación del fichero/directorio.

Utilizaremos la expresión de test, la cual podemos expresar con estas  tres sintaxis:

test EXPRESION
[ EXPRESION ] 
[[ EXPRESION ]]
Por cuestiones de portabilidad, si quieres que el script que vas a hacer sea utilizable en el mayor número de sistemas posible, te recomiendo que uses la sintaxis de "test" pues parece estar disponible en todas las shelll basada en norma POSIX.

La primera comprobación, la más básica que podemos hacer es comprobar si el elemento existe, sea un fichero, un directorio o un enlace, para essto emplearemos la opción -e

ahernan:/tmp$ FIC=/tmp/pp
ahernan:/tmp$ if test -e "$FIC"; then echo "$FIC existe"; fi
/tmp/pp existe
Si queremos afinar un poco más y preguntar si además de existir, sí se trata de un fichero, empleraremos la opción -f
ahernan:/tmp$ FIC=/tmp/pp
ahernan:/tmp$ if test -f "$FIC"; then echo "$FIC existe y es un fichero regular"; fi
/tmp/pp existe y es un fichero regular
Utilizando los otros formataos de expresar el "test", serían algo así como esto que os pongo a continuación, donde se ejecuta la parte a la derecha de los && cuando el resultado de la evaluación del test es verdadero, o a la derecha de los || cuando la evaluación del test es falso.
ahernan:/tmp$ FIC=/tmp/pp
ahernan:/tmp$ [[ -f $FIC ]] && echo "$FIC existe y es un fichero regular" || echo "$FIC no existe o no es un fichero regular"
/tmp/pp existe y es un fichero regular
Como veis, la potencia del comando reside en el parámetro que utilicemos. A continuación os enumero bastantes de sus opciones, no todas, pero si las que me parecen más útiles:

Tipo del descriptor:

-bDevuelve TRUE si existe y se trata de un Block device o special block file
-cDevuelve TRUE si exsite y se trata de un fichero de caracteres
-dDevuelve TRUE si existe y es un directorio
-fDevuelve TRUE si existe y es un fichero regular.
-SDevuelve TRUE si existe y es un socket.
-pDevuelve TRUE si existe y es un pipe
-LDevuelve TRUE si existe y es un enlace simbólico
-hDevuelve TRUE si existe y es un enlace simbólico

Permisos del descriptor:

-uDevuelve TRUE si existe y tiene el flag de set-user-id (suid) activo
-gDevuelve TRUE si existe y tiene el flag de set-group-id (sgid) activo
-kDevuelve TRUE si existe y activo el flag de sticky bit
-wDevuelve TRUE si existe y es escribible
-xDevuelve TRUE si existe y es ejecutable
-rDevuelve TRUE si existe y es leible

Otros acerca del descriptor:

-sDevuelve TRUE si existe y tienen tamaño distinto de 0
-GDevuelve TRUE si existe y el descriptor tiene el mismo grupo que el usuario que ejecuta el comando
-ODevuelve TRUE si exsite y el descriptor tiene el mismo propietario que el usuario que ejecuta el comando