Globbing

La shell bash no es capaz por si sola ni de reconocer ni de analizar expresiones regulares. Sin embargo tiene un proceso para descubrir/detectar nombres de fichero de una manera más o menos automatizada conocida con el nombre de expansión de nombre de fichero o también globbing.

Mediante el globbing y empleando caracteres especiales como \*, ?, ^, -, comas paréntesis, llaves y corchetes; bash puede analizar expresiones que le permiten sustituir dicha expresión por el conjunto de ficheros que verifican dicha expresión.

Veamos cual es el significado de cada uno de estos caracteres y como funcionan con varios ejemplos:

\* Sirve para sustituir cualquier conjunto de caracteres, incluso un conjunto vacío que este presente en el nombre de los ficheros a detectar. No detectará implicitamente ficheros que comiencen por punto

Ejemplos:

$ echo \*
Todos los ficheros que no empiecen por punto

$ echo .\*
Todos los ficheros que empiecen por punto

$ echo a\*
Todos los ficheros que empiecen por ‘a’

$ echo \*a\*
Todos los ficheros que contengan al menos una ‘a’

? Sirve para sustituir 1 caracter de cualquier tipo (excepto el punto al comienzo del nombre del fichero como en el caso del asterisco).

$ echo ???
Todos los ficheros que tengan 3 caracteres por nombre

$ echo ?a\*
Todos los ficheros cuyo segundo caracter sea una ‘a’

[] Para rangos de caracteres separados por guión o un conjunto de caracteres
Ejemplos:

$ echo [a-z]\*
Todos los ficheros que empiecen por una letra minúscula del alfabeto inglés

$ echo \*[0-9]
Todos los ficheros que terminen con un número

$ echo \*[abc]\*
Todos los ficheros que contengan una a, una b o una c minúscula

{} lista separada con comas de expansiones válidas. Permite combinar aditivamente varios expresiones de globbing

Ejemplo:
$ echo {\*[abc]\*,\*[0-9],hola,???}

^ Negación de un rango de caracteres

Ejemplo:
$ echo [^0-9]\*
Ficheros que no comienzan por numero

Globbing admite un modo extendido que habilita mas wildcards y posibilidades. Para tenerlo disponible debemos ejecutar:

$ shopt -s extglob

+, !, @ estarían ahora disponibles como wildcards

Un interesante y sutil punto a tener en cuenta es que el globbing lo realiza directamente el interprete bash y no los programas que lancemos a través de él ni el sistema operativo. Esto quiere decir que el globbing lo realizará el bash antes de ejecutar el programa al que sólo le llegarán los nombres de ficheros que hayan sido detectados correctamente mediante globbing. En la inmensa mayoría de los casos esto carece de importancia pero en otros si que la tiene. Por ejemplo, cuando ejecutamos programas a través de exec() o su familia de funciones amigas. Si no ejecutamos el programa a través de bash no tendremos disponible la expansión de nombre de ficheros.

Existe otro caso bien conocido en el que esta característica se vuelve importante. Imaginemos una carpeta que contiene cientos de miles de ficheros digamos más de cien mil (en realidad con tener más de 65535 nos llega). Por algún motivo (que bien podría ser este) queremos borrar estos ficheros. Entramos en este directorio y escribimos

$ rm -rf \*

Pero rm se niega a ejecutarlo dando este mensaje de error

-bash: /bin/rm: Argument list too long

¿Que es lo que pasa?

Pues que bash ha pasado al programa rm una lista con más de 65535 argumentos que es más de los permitidos para que rm (o cualquier otro programa de bash) pueda ejecutar a causa del globbing. Para solucionar esto podemos ejecutar por ejemplo:

find -type f -exec rm -f {} \;

Cuidado esta instrucción no es equivalente a la anterior aunque si es válida en este escenario. La diferencia radica en que la instrucción con find también borrará ficheros que comiencen por punto que estén en el directorio actual. Sin embargo rm -rf * no los borrará (aunque si los ficheros que comiencen con punto incluidos en subdirectorios del directorio actual).

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *