jueves, 5 de mayo de 2016

Operadores

Incluso con todos los test que proporciona find, aún podríamos necesitar una mejor forma de describir las relaciones lógicas entre los test. Por ejemplo, ¿qué pasa si necesitamos determinar si todos los archivos y subdirectorios de un directorio tienen permisos seguros? Podríamos buscar todos los archivos con permisos que no son 0600 y los directorios con permisos que no son 0700. Afortunadamente, find cuenta con una forma de combinar tests usando operadores lógicos para crear relaciones lógicas más complejas. Para expresar el test mencionado anteriormente, podríamos hacer ésto:

[me@linuxbox ~]$ find ~ \( -type f -not -perm 0600 \) -or \( -type d -not -perm 0700 \)

¡Uff! Seguro que te parece raro. ¿Qué es todo eso? Realmente, los operadores no son tan complicados una vez que los conoces. Aquí hay una lista:

Tabla 17-4: Operadores lógicos de find
Operador
Descripción
-and Comprueba si los tests en ambos lados del operador son verdad. Puede abreviarse a -a. Fíjate que cuando no hay operador presente, -and está implícito por defecto.
-or Comprueba si algún test, situado en cualquier lado del operador, es verdadero. Puede abreviarse a -o.
-not Comprueba si el test que sigue al operador es falso. Puede abreviarse con un signo de exclamación (!).
( ) Agrupa tests y operadores juntos para formar una expresión más grande. Se usa para controlar la precedencia de las evaluaciones lógicas. Por defecto, find evalua de izquierda a derecha. A menudo es necesario anular la precedencia por defecto para obtener el resultado deseado. Incluso si no es necesario, a veces es útil incluir los caracteres de agrupamiento para mejorar la legibilidad del comando. Fíjate que como los paréntesis tienen significado especial para el shell, deben ir entrecomillados cuando se usan en la línea de comandos, para permitir que sean pasados como argumentos de find. Normalmente el carácter de la barra invertida se usa para tratarlos como caracteres de escape.

Con esta lista de operadores a mano, deconstruyamos nuestro comando find. Cuando lo vemos desde el nivel superior, vemos que nuestros tests están ordenados como dos grupos separados por un operador -or:

( expresión 1 ) -or (expresión 2 )

Esto tiene sentido, ya que estamos buscando archivos con una determinada configuración de permisos y directorios con una configuración distinta. Si estamos buscando tanto archivos como directorios, ¿por qué usamos -or en lugar de -and? Porque a medida que find busca a través de archivos y directorios, cada uno es evaluado para ver si coincide con los tests especificados. Queremos saber si es un archivo con permisos incorrectos o un directorio con permisos incorrectos. No puede ser los dos al mismo tiempo. Así que si expandimos las expresiones agrupadas, podemos verlo de esta forma:

( archivo con malos permisos ) -or ( directorio con malos permisos )

Nuestro próximo desafío es cómo buscar “malos permisos” ¿Cómo lo hacemos? En realidad no lo haremos. Lo que buscaremos serán “permisos no buenos”, ya que sabemos cuáles son “permisos buenos”. En el caso de archivos, definimos bueno como 0600 y para directorios, 0700. La expresión que buscará archivos con permisos “no buenos” es:

-type f -and -not -perms 0600

y para directorios:

-type d -and -not -perms 0700

Cómo apuntamos en la tabla de operadores anterior, el operador -and puede eliminarse con seguridad, ya que está implícito por defecto. Así que si ponemos todo junto, tenemos nuestro comando definitivo:

find ~ ( -type f -not -perms 0600 ) -or ( -type d -not -perms 0700 )

Sin embargo, como los paréntesis tienen un significado especial para el shell, tenemos que “escaparlos” para prevenir que el shell trate de interpretarlos. Precediendo cada uno con una barra invertida conseguimos el truco.

Hay otra característica de los operadores lógicos que es importante entender. Digamos que tenemos dos expresiones separadas por un operador lógico:

expr1 -operador expr2

En todos los casos, expr1 siempre se llevará a cabo; sin embargo, el operador determinará si expr2 se realizará. Aquí tenemos cómo funciona:

Tabla 17-5: Lógica AND/OR de find
Resultado de expr1
Operador
expr2...
Verdadero -and se ejecuta siempre
Falso -and no se ejecuta
Verdadero -or no se ejecuta
Falso -or se ejecuta siempre

¿Por qué ocurre ésto? Para mejorar el rendimiento. Tomemos, por ejemplo, -and. Sabemos que la expresión expr1 -and expr2 no puede ser verdadera si el resultado de expr1 es falso, luego no tiene sentido que se ejecute expr2. Igualmente, si tenemos la expresión expr1 -or expr2 y el resultado de expr1 es verdadero, no es necesario que se ejecute la expr2 ya que ya sabemos que la expresión expr1 -or expr2 es verdadera.

Ok, así que ayuda a que sea más rápido. ¿Por qué es importante? Es importante porque podemos contar con este comportamiento para controlar como se realizan las acciones, como veremos pronto.

No hay comentarios:

Publicar un comentario