Prueba tus scripts de shell desde una ruta con espacios
¿El detector de bugs de shell más barato? Una carpeta con un espacio en el nombre. Las variables sin comillas se ven bien durante meses — hasta que una ruta contiene un espacio, el shell la divide en dos argumentos y tu script hace algo que nunca quisiste. Puedes comprar esa falla temprano y gratis: ejecuta el script desde un directorio temporal cuya ruta tenga un espacio.
Por qué un solo espacio rompe tanto
Bash examina los resultados de la expansión de parámetros, la sustitución de comandos y la expansión aritmética sin comillas para hacer word splitting, usando $IFS — por defecto espacio, tab y salto de línea. Así que rm $file sobre 01 - intro.mp3 se convierte en rm con tres argumentos, no uno. La advertencia más famosa de ShellCheck, SC2086, existe exactamente por esto: las expansiones sin comillas primero se dividen por IFS y luego cada pedazo se expande como glob. Dos transformaciones silenciosas, ambas incorrectas para nombres de archivo.
La solución es un par de caracteres — "$file" en vez de $file — pero el bug se esconde porque los desarrolladores prueban en ~/projects/myrepo, una ruta con cero espacios.
El arnés de 60 segundos
Haz que el entorno de falla sea el entorno de prueba por defecto:
# 1. A temp dir with a space in its path — on purpose
dir="$(mktemp -d "${TMPDIR:-/tmp}/space test.XXXXXX")"
# 2. Run the script from there
cp myscript.sh "$dir/"
cd "$dir" && bash myscript.sh
# 3. Clean up
rm -rf "$dir"
mktemp -d crea el directorio; la plantilla solo necesita al menos tres X consecutivas en el último componente, y nada impide poner un espacio antes. Cada $dir, $PWD, $(dirname "$0") o cd $target sin comillas dentro del script ahora falla a lo grande, ahí mismo — en vez de fallar en silencio en la máquina de un usuario cuya carpeta personal es /Users/Ana Maria.
Qué ejercitar una vez adentro
| Modo de falla | Cómo provocarlo |
|---|---|
| Word splitting / globbing | La propia ruta con espacio — cualquier expansión sin comillas se rompe |
| Suposiciones sobre el directorio actual | Ejecuta desde el directorio temporal, no desde la raíz del repo; las rutas relativas que "funcionaban" dejan de funcionar |
| Variables de entorno faltantes | env -i bash myscript.sh — un entorno vacío expone cada $VAR que asumiste definida |
| Subprocesos fallidos | Apunta el script a un comando que sale con código distinto de cero; verifica que se detenga en vez de continuar |
| Ejecuciones repetidas | Córrelo dos veces en el mismo directorio — los bugs de idempotencia (mkdir sin -p, appends duplicados) aparecen en la segunda corrida |
Primero lint, después ejecutar
El análisis estático atrapa la clase de bug de comillas antes de ejecutar nada. ShellCheck marca las expansiones sin comillas, y la Google Shell Style Guide lo recomienda "para todos los scripts, grandes o pequeños" — junto con su propia regla de comillas: siempre pon entre comillas las cadenas que contienen variables, sustituciones de comandos, espacios o metacaracteres del shell. El orden importa: el lint atrapa lo estáticamente visible; la corrida desde la ruta con espacio atrapa los casos dinámicos que el lint no ve (valores que llegan en tiempo de ejecución desde find, argumentos o configuración).
Movidas de usuario avanzado
- Intégralo en CI. Un job de cinco líneas que copia tus scripts a una ruta de
mktemp -dcon espacio y corre la suite desde ahí convierte esto de hábito en garantía. - Ve más allá de los espacios. Los saltos de línea y los caracteres glob (
*,?) en nombres de archivo rompen aún más scripts. Un directorio llamado$(printf 'a b\nc*')es la versión adversarial de esta prueba. - Atrapa la limpieza con trap.
trap 'rm -rf "$dir"' EXITelimina el directorio temporal incluso cuando el script falla a mitad de camino — y sí, ese"$dir"también necesita sus comillas. - Lee BashPitfalls una vez al año. El clásico
for f in $(ls *.mp3)— iterar sobre palabras en vez de archivos — es el mismo mecanismo de word splitting en forma de bucle, y la lista de soluciones del wiki sirve como checklist para tu arnés.
Recursos
- ShellCheck SC2086 — double quote to prevent globbing and word splitting
- Bash Reference Manual — Word Splitting
- Greg's Wiki — Bash Pitfalls
- Google Shell Style Guide — quoting y ShellCheck
- Página man de mktemp(1)
¿Construyendo una función con IA? Yeda AI diseña, audita y entrega sistemas LLM de producción.