Yeda AI Tips · #090

English

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 fallaCómo provocarlo
Word splitting / globbingLa propia ruta con espacio — cualquier expansión sin comillas se rompe
Suposiciones sobre el directorio actualEjecuta desde el directorio temporal, no desde la raíz del repo; las rutas relativas que "funcionaban" dejan de funcionar
Variables de entorno faltantesenv -i bash myscript.sh — un entorno vacío expone cada $VAR que asumiste definida
Subprocesos fallidosApunta el script a un comando que sale con código distinto de cero; verifica que se detenga en vez de continuar
Ejecuciones repetidasCó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

Recursos

¿Construyendo una función con IA? Yeda AI diseña, audita y entrega sistemas LLM de producción.

Habla con nosotros · Lee el blog