Ejecutas el script. El archivo está justo ahí. Puedes ls verlo, completar con tab, mirarlo como si te debiera dinero.
Y WSL responde: No such file or directory.
Este error es el truco de magia favorito de WSL: hace que un archivo real “desaparezca” atacando la ruta en una capa distinta a la que tú estás mirando.
La solución rara vez es “crear el archivo”. La solución es entender en qué sistema de ficheros estás, qué sintaxis de ruta está en juego y qué traductor está reescribiendo silenciosamente tus suposiciones.
El problema real: tu ruta es válida… en el universo equivocado
WSL no es tanto “Linux en Windows” como “Linux al lado de Windows con un tratado”. Ese tratado incluye traducción de rutas, capas de montaje,
semántica de nombres de archivo y un puente de interoperabilidad que intenta ser útil hasta que no lo es.
Cuando WSL dice “No such file or directory”, podría significar:
- El archivo existe, pero el intérprete nombrado en el shebang no existe (o no se puede encontrar).
- El archivo existe, pero estás en
/mnt/cy el mapeo de permisos/metadata lo hace efectivamente no ejecutable. - El archivo existe, pero la ruta contiene problemas de escape propios de Windows (espacios, paréntesis, backslashes) y tu shell te está engañando.
- El archivo existe, pero tiene CRLF, por lo que la ruta del intérprete es en realidad
/bin/bash\r, que efectivamente no existe. - El archivo existe, pero estás mezclando rutas UNC, enlaces simbólicos o comportamiento de mayúsculas/minúsculas y terminas en otro lugar.
- El archivo existe, pero lo estás llamando desde un proceso de Windows que “amablemente” reescribe los argumentos.
Tu trabajo es identificar qué capa está generando la condición de “ausencia”. No adivines. Diagnostica.
Guía rápida de diagnóstico
Este es el orden que reviso cuando una página de on-call dice “pipeline falla en WSL, archivo no encontrado, el archivo está presente.”
Está optimizado para llegar a la causa raíz rápido, no para enseñarte fundamentos de Linux.
Primero: ¿es un problema de ruta o del intérprete?
- Si es un script: revisa el shebang y los finales de línea (
head -n1,file). - Si es un binario: revisa la arquitectura y el loader (
file,ldd).
Segundo: ¿dónde está localizado el archivo?
/home(ext4 dentro del VHDX de WSL2) se comporta como Linux./mnt/c(DrvFs) se comporta como “Linux hablando con NTFS a través de una capa de compatibilidad”.- Los recursos de red añaden otra capa de compatibilidad. Ahí es donde la alegría va a jubilarse.
Tercero: ¿quién llama a quién?
- Linux que llama a Linux suele ser coherente.
- Linux que llama a EXEs de Windows vía interoperabilidad tiene casos límite de comillas/rutas.
- Windows que llama a WSL (
wsl.exe) puede reescribir el directorio de trabajo y los argumentos.
Cuarto: valida los bytes exactos de la ruta
- Busca caracteres ocultos: CR, espacios no separables, comillas “inteligentes”, normalización Unicode.
- Confirma que la entrada del directorio existe y es alcanzable (
stat), no solo listada.
Quinto: identifica opciones de montaje y comportamiento de metadata
- Las opciones de montaje de DrvFs deciden si
chmod +xsignifica algo. - La sensibilidad a mayúsculas puede ser por directorio en NTFS; puede cambiar el comportamiento entre máquinas.
Ejecuta las tareas de la siguiente sección en orden hasta que algo parezca mal. Lo hará. Ese es el punto.
Modelo de rutas de WSL, explicado para quien gestiona producción
WSL2 te da un kernel Linux real—y luego te entrega un montón de traductores
En WSL2, tu distribución Linux vive en un sistema de archivos ext4 dentro de un disco virtual (VHDX). Esa es la parte “Linux real”.
Tus unidades de Windows se vuelven visibles en Linux vía montajes DrvFs, típicamente bajo /mnt/c, /mnt/d, etc.
Esos dos mundos difieren en formas que importan para “archivo no encontrado”:
- Sintaxis de rutas: Linux usa
/, Windows usa\y letras de unidad. - Comportamiento de mayúsculas: Linux es sensible a mayúsculas; Windows históricamente no lo es (pero puede configurarse por directorio).
- Semántica de ejecutables: Linux usa bits de modo e intérpretes; Windows usa extensiones y cabeceras PE.
- Enlaces simbólicos: Los symlinks de Linux son nativos; los symlinks de Windows son… un debate de políticas.
Cuando WSL dice que no encuentra un archivo, puede significar que no encuentra una entrada de directorio—o que no puede ejecutarlo
Linux tiene una taxonomía de errores maravillosamente directa. Varios problemas distintos colapsan en mensajes similares:
ENOENT: no existe tal archivo o directorio (también se lanza cuando el intérprete o el cargador dinámico falta).EACCES: permiso denegado (a menudo lo que esperabas ver, pero no viste).ENOTDIR: un componente de la ruta no era un directorio (puede ocurrir con destinos de symlink extraños).
WSL añade un giro: las capas de traducción pueden devolver ENOENT cuando el lado Linux solicita algo que el lado Windows no puede representar.
El resultado es un error que es técnicamente correcto y operacionalmente molesto.
La interoperabilidad es poderosa, pero es un campo minado de comillas y directorio de trabajo
WSL te permite ejecutar ejecutables de Windows desde Linux y comandos de Linux desde Windows. Eso es genial hasta que pasas:
- Rutas con espacios o paréntesis
- Rutas que parecen opciones (comienzan con
-) - Rutas UNC (
\\server\share) - Argumentos que contienen backslashes que tu shell “amablemente” interpreta
En términos de incidentes: la interoperabilidad aumenta tu radio de impacto. Es conveniente en desarrollo; es frágil en la automatización a menos que seas disciplinado.
Hechos e historia interesantes (porque el pasado sigue rompiendo tu build)
- Hecho 1: WSL1 traducía llamadas al sistema de Linux a llamadas de Windows. WSL2 cambió a un kernel Linux real en una VM ligera, cambiando drásticamente las compensaciones de rendimiento del sistema de archivos.
- Hecho 2: Los montajes por defecto de unidades Windows viven bajo
/mntporque las primeras versiones de WSL buscaban parecerse a un layout típico de Linux sin colisionar con directorios de la distribución. - Hecho 3: NTFS históricamente se comportó de forma insensible a mayúsculas pero preservando el caso; Windows moderno puede habilitar sensibilidad por directorio, lo que hace el comportamiento entre herramientas cruzadas… picante.
- Hecho 4: El clásico problema CRLF precede a WSL por décadas; es un artefacto de terminal y herramientas de las convenciones de texto DOS/Windows encontrándose con las convenciones Unix.
- Hecho 5: Linux reporta ENOENT no solo cuando falta el archivo destino, sino también cuando el intérprete ELF o el cargador dinámico referenciado por un binario no puede localizarse.
- Hecho 6: Las rutas de Windows pueden contener legalmente caracteres que son sintácticamente significativos para shells (espacios, paréntesis, ampersands). En una tubería de shell, eso no es “solo una ruta”, es un incidente.
- Hecho 7: El mapeo de permisos de DrvFs solía ser una fuente constante de confusión; existen opciones de montaje como
metadataespecíficamente para preservar bits de modo de Linux en sistemas de archivos de Windows. - Hecho 8: Las configuraciones de finales de línea de Git (autocrlf) son una de las razones más comunes por las que un script se vuelve “no ejecutable” en Linux mientras se ve bien en editores de Windows.
- Hecho 9:
wsl.execambió su comportamiento entre versiones de Windows respecto al directorio de trabajo por defecto y las banderas de traducción de rutas; los scripts que asumen el comportamiento de una versión pueden fallar en otra.
Tareas prácticas: comandos, salidas y qué significan
Abajo están los diagnósticos reales que uso. Cada tarea incluye (1) el comando, (2) qué podrías ver y (3) la decisión que tomas.
No los ejecutes todos a ciegas en una pipeline de producción—ejecútalos en el entorno que falla con las entradas que fallan.
Tarea 1: Confirma si estás en WSL1 o WSL2 (cambia el comportamiento del sistema de archivos)
cr0x@server:~$ uname -a
Linux server 5.15.146.1-microsoft-standard-WSL2 #1 SMP Fri Jan 12 18:22:05 UTC 2024 x86_64 GNU/Linux
Significado: microsoft-standard-WSL2 indica WSL2. Si ves WSL1, la traducción de rutas y la semántica del sistema de archivos difieren.
Decisión: Si es WSL1, espera más rarezas de traducción de llamadas al sistema; si es WSL2, enfócate mucho en montajes DrvFs y rendimiento/metadata entre sistemas de archivos.
Tarea 2: Identifica dónde vive realmente el archivo (ext4 de Linux vs unidad de Windows)
cr0x@server:~$ df -T /home /mnt/c | sed -n '1,3p'
Filesystem Type 1K-blocks Used Available Use% Mounted on
/dev/sdc ext4 263174212 93481244 156278972 38% /
C:\ 9p 976762876 512331244 464431632 53% /mnt/c
Significado: ext4 es el sistema de archivos respaldado por VHDX de WSL2; 9p aquí representa el canal de montaje de la unidad de Windows.
Decisión: Si el archivo que falla está bajo /mnt/c, trátalo como “extranjero”. Mueve artefactos de build/ejecución a $HOME si quieres menos sorpresas.
Tarea 3: Verifica que la ruta no esté mintiendo (stat no miente como tu terminal)
cr0x@server:~$ stat "/mnt/c/Users/alex/Projects/demo/run.sh"
File: /mnt/c/Users/alex/Projects/demo/run.sh
Size: 231 Blocks: 0 IO Block: 4096 regular file
Device: 33h/51d Inode: 0 Links: 1
Access: (0777/-rwxrwxrwx) Uid: ( 1000/ cr0x) Gid: ( 1000/ cr0x)
Access: 2026-02-05 11:34:40.000000000 +0000
Modify: 2026-02-05 11:34:39.000000000 +0000
Change: 2026-02-05 11:34:39.000000000 +0000
Significado: Si stat falla con ENOENT, verdaderamente no tienes una ruta alcanzable desde la perspectiva de Linux. Si tiene éxito, el archivo existe; la ejecución aún puede fallar por otras razones.
Decisión: Si stat funciona pero la ejecución falla con “No such file”, salta inmediatamente al shebang y a los finales de línea.
Tarea 4: Si ejecutar un script falla, revisa la primera línea (shebang)
cr0x@server:~$ head -n1 /mnt/c/Users/alex/Projects/demo/run.sh | cat -A
#!/bin/bash^M$
Significado: Ese ^M es un retorno de carro. La ruta del intérprete de tu script es efectivamente /bin/bash\r, que no existe.
Decisión: Convierte los finales de línea a LF (dos2unix) o configura Git/tu editor para que deje de reintroducir CRLF.
Tarea 5: Confirma finales de línea y tipo de archivo con file
cr0x@server:~$ file /mnt/c/Users/alex/Projects/demo/run.sh
/mnt/c/Users/alex/Projects/demo/run.sh: Bourne-Again shell script, ASCII text, with CRLF line terminators
Significado: Este es el modo clásico de fallo “existe pero no puede ejecutarse”.
Decisión: Arregla los finales de línea y haz commit del arreglo, o seguirás arreglándolo cada lunes.
Tarea 6: Convierte CRLF a LF de forma segura (y verifica)
cr0x@server:~$ dos2unix /mnt/c/Users/alex/Projects/demo/run.sh
dos2unix: converting file /mnt/c/Users/alex/Projects/demo/run.sh to Unix format...
cr0x@server:~$ file /mnt/c/Users/alex/Projects/demo/run.sh
/mnt/c/Users/alex/Projects/demo/run.sh: Bourne-Again shell script, ASCII text
Significado: La ruta del intérprete ahora está limpia.
Decisión: Si el script sigue fallando, revisa el bit de ejecución y las opciones de montaje a continuación.
Tarea 7: Revisa permisos de ejecución y comportamiento de metadata del montaje
cr0x@server:~$ ls -l /mnt/c/Users/alex/Projects/demo/run.sh
-rwxrwxrwx 1 cr0x cr0x 231 Feb 5 11:34 /mnt/c/Users/alex/Projects/demo/run.sh
Significado: En DrvFs sin metadata, los permisos pueden ser sintéticos; todo puede parecer ejecutable aunque la política lo contradiga. O al revés: haces chmod +x y no se mantiene.
Decisión: Si los cambios del bit de ejecución no persisten o el comportamiento difiere entre máquinas, inspecciona /etc/wsl.conf y las opciones de montaje actuales.
Tarea 8: Inspecciona opciones de montaje de DrvFs (la raíz de muchos casos “funcionaba ayer”)
cr0x@server:~$ mount | grep -E ' /mnt/c '
C:\ on /mnt/c type 9p (rw,relatime,dirsync,aname=drvfs;path=C:\;uid=1000;gid=1000;metadata;umask=22;fmask=11;case=off)
Significado: metadata está presente, así que los bits de modo de Linux pueden almacenarse en atributos extendidos de NTFS. case=off sugiere comportamiento insensible a mayúsculas.
Decisión: Si falta metadata y dependes de bits ejecutables o symlinks, actívalo en /etc/wsl.conf y reinicia WSL.
Tarea 9: Valida la existencia del intérprete del shebang (no siempre es /bin/bash)
cr0x@server:~$ head -n1 ./run.sh
#!/usr/bin/env bash
cr0x@server:~$ command -v env
/usr/bin/env
Significado: Usar /usr/bin/env es portátil, pero solo si env existe (normalmente sí) y el intérprete objetivo existe en PATH.
Decisión: Si command -v bash falla, instálalo o arregla PATH. Si env tiene CRLF, vuelves a la Tarea 4.
Tarea 10: Si un binario falla con ENOENT, revisa loader/dinámica y arquitectura
cr0x@server:~$ file ./tool
./tool: ELF 64-bit LSB pie executable, x86-64, dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, not stripped
cr0x@server:~$ ldd ./tool | sed -n '1,6p'
linux-vdso.so.1 (0x00007ffc6c5f8000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fda1b0d0000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fda1aeb0000)
/lib64/ld-linux-x86-64.so.2 (0x00007fda1b2f0000)
Significado: Si la ruta del intérprete en file apunta a algo que falta, ejecutar el binario puede dar “No such file or directory.”
Decisión: Si ldd muestra “not found” para alguna librería, instala dependencias. Si falta la ruta del intérprete, probablemente estás ejecutando un binario compilado para otra distro/arquitectura.
Tarea 11: Confirma directorio de trabajo actual y resolución de symlinks
cr0x@server:~$ pwd -P
/mnt/c/Users/alex/Projects/demo
cr0x@server:~$ readlink -f .
/mnt/c/Users/alex/Projects/demo
Significado: Si tu tooling depende de symlinks o rutas relativas, un pwd distinto al esperado puede romper concatenaciones de rutas.
Decisión: En automatización, resuelve a rutas absolutas pronto y regístralas. Si estás en /mnt/c, considera reubicar la ejecución al sistema de archivos Linux.
Tarea 12: Revisa si hay “comillas inteligentes” de Windows u oddidades Unicode en nombres de archivo
cr0x@server:~$ ls | cat -A
run.sh$
deploy–prod.sh$
Significado: Ese nombre contiene un en dash (–) no un guion (-). El comando que pegaste usa -, así que el archivo está “ausente”.
Decisión: Renombra el archivo a nombres seguros ASCII, o al menos deja de pegar desde texto enriquecido. La automatización odia la tipografía.
Tarea 13: Prueba explícitamente la invocación Windows→WSL y la traducción de rutas
cr0x@server:~$ wsl.exe -e bash -lc 'pwd; ls -l ./run.sh'
/mnt/c/Users/alex/Projects/demo
-rwxrwxrwx 1 cr0x cr0x 231 Feb 5 11:34 ./run.sh
Significado: Cuando Windows lanza WSL, el directorio de trabajo podría no ser lo que tu script espera a menos que lo establezcas.
Decisión: En CI o el Programador de tareas, siempre establece explícitamente el directorio de trabajo o pasa rutas absolutas.
Tarea 14: Convierte rutas de Windows a rutas WSL (y valida)
cr0x@server:~$ wslpath "C:\Users\alex\Projects\demo\run.sh"
/mnt/c/Users/alex/Projects/demo/run.sh
cr0x@server:~$ test -e "$(wslpath 'C:\Users\alex\Projects\demo\run.sh')" && echo OK || echo MISSING
OK
Significado: wslpath es la forma menos mala de traducir rutas, especialmente cuando se llama desde contextos Windows.
Decisión: Estandariza el uso de ayudantes de traducción de rutas en scripts en lugar de implementar reemplazos de cadenas caseros.
Tarea 15: Diagnostica problemas de comillas con espacios y paréntesis (trampa clásica de interoperabilidad)
cr0x@server:~$ p="/mnt/c/Program Files (x86)/Vendor Tool/bin/tool.exe"; test -e "$p" && echo EXISTS || echo MISSING
EXISTS
cr0x@server:~$ "$p" --version
VendorTool 4.2.1
Significado: Si no lo pones entre comillas, el shell divide por espacios y los paréntesis se vuelven sintaxis. Entonces “No such file” es la parte menos confusa.
Decisión: Pon entre comillas cada ruta. En revisiones de código, trata rutas sin comillas como SQL sin escape: no siempre explotable, siempre un riesgo.
Tarea 16: Inspecciona /etc/wsl.conf para la configuración de montajes (el archivo de política silenciosa)
cr0x@server:~$ sed -n '1,120p' /etc/wsl.conf
[automount]
enabled = true
options = "metadata,umask=22,fmask=11"
mountFsTab = false
Significado: Esto controla cómo se montan las unidades de Windows. metadata es la opción importante para permisos; umask/fmask afectan los modos por defecto.
Decisión: Si esto falta o es inconsistente entre máquinas, estandarízalo. La deriva aquí causa el clásico “funciona en mi portátil” como servicio.
Errores comunes: síntoma → causa raíz → solución
1) Síntoma: “No such file or directory” al ejecutar un script que claramente existe
Causa raíz: Finales de línea CRLF en la línea del shebang, resultando en /bin/bash^M.
Solución: Convierte a LF (dos2unix file), aplica LF en atributos de Git y evita que tu editor “ayude”.
2) Síntoma: “No such file or directory” solo cuando se ejecuta desde Windows (Task Scheduler, tarea de VS Code, runner de CI)
Causa raíz: Directorio de trabajo incorrecto, o el quoting de argumentos cambia al cruzar la frontera Windows↔WSL.
Solución: Usa wsl.exe -e bash -lc con cd explícito, pasa rutas absolutas y traduce rutas de Windows con wslpath.
3) Síntoma: chmod +x “funciona” pero la ejecución sigue comportándose de forma inconsistente en /mnt/c
Causa raíz: Opciones de montaje de DrvFs sin metadata (o política inconsistente entre máquinas).
Solución: Configura /etc/wsl.conf para habilitar metadata; reinicia WSL. Prefiere ejecutar herramientas de build en el sistema de archivos Linux ($HOME) cuando sea posible.
4) Síntoma: El archivo existe, pero ./tool devuelve “No such file or directory”
Causa raíz: Falta el cargador dinámico o dependencia de librería compartida; ENOENT puede lanzarse por un intérprete ELF ausente.
Solución: file tool y ldd tool. Instala las libs necesarias o recompila para la distro/entorno objetivo de WSL.
5) Síntoma: Una ruta funciona en un repo pero no en otro; mismo nombre de archivo, comportamiento distinto
Causa raíz: Desajuste de sensibilidad a mayúsculas. Un directorio puede ser sensible en NTFS; otro no. O las herramientas usan mayúsculas inconsistentes en imports/rutas.
Solución: Normaliza el uso de mayúsculas en código y scripts de build. Evita depender de comportamiento insensible a mayúsculas. Trata repos alojados en Windows como caos de mayúsculas salvo que se demuestre lo contrario.
6) Síntoma: “No such file or directory” con rutas que contienen guiones Unicode o comillas inteligentes
Causa raíz: Los bytes del nombre de archivo no coinciden con lo que escribiste. La puntuación “bonita” se parece idéntica hasta que arruina tu noche.
Solución: Renombra archivos a nombres seguros ASCII, o copia exactamente el nombre desde ls. Prefiere rutas generadas por máquina para automatización.
7) Síntoma: Los scripts fallan solo en recursos de red mapeados en unidades de Windows
Causa raíz: Capa adicional de traducción (SMB/CIFS, rediractor de Windows, luego DrvFs). Permisos y semántica de cambio de archivos pueden diferir.
Solución: Copia o sincroniza al sistema de archivos Linux antes de ejecutar; evita ejecutar scripts directamente desde recursos en red.
8) Síntoma: “No such file or directory” al usar rutas relativas en makefiles o scripts npm
Causa raíz: La herramienta cambia su directorio de trabajo internamente, o asumiste que $PWD es estable al cruzar fronteras de interoperabilidad.
Solución: Resuelve rutas usando detección de la raíz del repositorio, rutas absolutas y regístralas. En scripts de shell, usa script_dir="$(cd "$(dirname "$0")" && pwd -P)".
Tres micro-historias corporativas desde las trincheras de rutas
Micro-historia 1: El incidente causado por una suposición equivocada
Una empresa mediana ejecutaba un runner de CI basado en Windows que realizaba pasos de build de Linux vía WSL.
Había sido estable durante meses, principalmente porque el equipo rara vez tocaba las imágenes del runner.
Luego llegó un repositorio nuevo con un script de arranque “simple” comprometido por alguien que vivía en editores de Windows.
El script estaba presente. Los logs del pipeline mostraban que estaba listado en el directorio. Pero cada intento de ejecutarlo terminaba en:
“No such file or directory.” El primer respondededor hizo lo que hacen los respondedores: volvió a ejecutar el job. Mismo resultado.
Luego probaron rutas absolutas. Mismo resultado. Luego copiaron el archivo por todos lados, como mover una planta para ver si deja de morir.
La suposición equivocada fue sutil: todos asumieron que ENOENT significaba “archivo faltante”. El archivo no faltaba.
La ruta del intérprete sí. CRLF en el shebang convirtió /usr/bin/env en /usr/bin/env\r.
El kernel no pudo encontrar ese intérprete, así que informó ENOENT al ejecutar el script.
Lo arreglaron con la imposición de finales de línea en el borde del repositorio, no diciendo a los desarrolladores “tengan cuidado”.
Un hook pre-commit ayudó, pero la verdadera victoria fue un paso de CI que fallaba rápido cuando un shebang contenía CR.
Eso convirtió un error fantasma en uno legible.
Lección del postmortem: no asumas nada sobre “archivo no encontrado” hasta que hayas revisado la línea del intérprete.
Las máquinas son literales. Las personas son optimistas. El optimismo no pasa builds.
Micro-historia 2: La optimización que salió mal
Otro equipo intentó acelerar su entorno de desarrollo basado en WSL. Mantuvieron su repo en /mnt/c
para que las herramientas de Windows (indexadores del IDE, exclusiones de antivirus, watchers) pudieran accederlo fácilmente.
Pero las builds eran lentas, así que hicieron una “cosa inteligente”: compilar en WSL pero mantener los artefactos en /mnt/c
para que Windows los recogiera sin copiar.
La primera semana fue genial. Algunas cargas mejoraron, mayormente porque las caches estaban calientes y nadie golpeó casos límite.
Luego un candidato de release falló al empaquetar. El empaquetador se quejó de que un script generado faltaba.
El script existía, pero de forma intermitente “no se podía encontrar” durante pasos paralelos.
El problema no fue místico. Habían puesto una carga concurrente intensa en un puente de sistema de archivos que no se comportaba como un ext4 nativo.
Las actualizaciones de metadata, notificaciones de archivo y semánticas de renombrado bajo paralelismo pesado expusieron ventanas de timing.
La lógica de reintento del pipeline lo empeoró cubriendo las primeras señales.
Lo arreglaron con lo aburrido pero correcto: mover el repo y salidas de build al sistema de archivos Linux ($HOME)
y solo copiar artefactos finales a Windows cuando fuese necesario. El rendimiento se volvió consistente. Las fallas dejaron de ser “intermitentes.”
Lección: “menos copias” no siempre es “más rápido”. A veces es simplemente “más cerca de la parte extraña del sistema”.
Micro-historia 3: La práctica aburrida pero correcta que salvó el día
Una empresa regulada tenía una flota mixta: algunos desarrolladores usaban WSL, otros laptops Linux, y CI corría en Linux.
Su modelo de amenaza y requisitos de auditoría los hacía alérgicos a “magia específica del desarrollador”. Esto fue molesto, pero forzó disciplina.
Estandarizaron un conjunto pequeño de puntos de entrada de build con reglas estrictas:
los scripts debían usar #!/usr/bin/env bash, tener finales LF, no asumir la disposición de /bin y registrar sus rutas resueltas.
Cada repo tenía una comprobación de saneamiento de rutas que corría en menos de un segundo.
Un día, una actualización de Windows cambió algo menor sobre cómo un desarrollador lanzaba WSL desde su IDE.
Una ruta relativa usada por un script auxiliar se rompió—solo en la máquina de ese desarrollador.
La comprobación de saneamiento imprimió inmediatamente: “Working directory is /mnt/c/…; expected repo root. Aborting.”
No perdieron media jornada en una cacería de fantasmas. No lo “arreglaron” pidiendo a todos reinstalar.
Cambiaron la tarea del IDE para hacer cd explícito y siguieron con su trabajo.
Lección: directorios de trabajo explícitos y validación temprana son aburridos. Por eso funcionan.
Listas de verificación / plan paso a paso
Lista A: Cuando ocurre “No such file or directory” al ejecutar un script
- Ejecuta
stat "path". Si falla, es realmente un problema de ruta. Si tiene éxito, continúa. - Ejecuta
head -n1 file | cat -A. Si ves^M, arregla finales de línea. - Ejecuta
file file. Confirma que es un script con terminadores LF. - Verifica que exista el intérprete:
command -v bashols -l /bin/bash. - Revisa el bit de ejecución:
ls -l file. Si está en/mnt/c, confirma que las opciones de montaje incluyanmetadatasi dependes de ello. - Si se invoca desde Windows, establece explícitamente el directorio de trabajo y pasa rutas absolutas.
Lista B: Cuando ocurre “No such file or directory” al ejecutar un binario
stat ./binaryyls -lpara asegurar que existe y es ejecutable.file ./binarypara confirmar arquitectura y ruta del intérprete.ldd ./binaryy busca “not found”.- Si falta el intérprete, probablemente ejecutas un binario compilado para otra distro; recompila dentro de WSL o empata la imagen base.
- Mueve el binario al sistema de archivos Linux si está en
/mnt/cy el comportamiento es inconsistente.
Lista C: Estandariza montajes WSL para reducir la inestabilidad por rutas
- Crea/verifica
/etc/wsl.confcon opciones de automount apropiadas para tu organización. - Decide si quieres
metadata. Si ejecutas scripts desde/mnt/c, probablemente sí. - Reinicia WSL (cierra las distribuciones y luego reinicia el servicio WSL desde Windows).
- Documenta una ubicación “bendecida” para repos: o el sistema de archivos Linux para build/ejecución, o el sistema Windows para edición—pero no finjas que son idénticos.
Exactamente una cita, porque no estamos aquí para empapelar el problema con posters de sabiduría:
“La esperanza no es una estrategia.” — Gene Kranz
Chiste 1: Los errores de rutas en WSL son como calcetines en la secadora: eventualmente todo desaparece y nadie admite tocar la configuración.
Preguntas frecuentes
1) ¿Por qué Linux dice “No such file or directory” cuando el archivo existe?
Porque ENOENT puede referirse a un intérprete faltante (shebang), a un cargador dinámico faltante para un binario ELF, o a un componente de ruta faltante tras la traducción.
En WSL, las capas de traducción y el comportamiento de montaje añaden más formas de generar ENOENT.
2) ¿Cómo detecto rápido si es CRLF?
Ejecuta head -n1 script | cat -A y busca ^M, o ejecuta file script y comprueba “with CRLF line terminators.”
3) ¿Es malo mantener código bajo /mnt/c?
No es moralmente malo. Es operacionalmente arriesgado para cargas de trabajo intensivas en Linux. Si compilas, ejecutas muchas operaciones en pequeños archivos o dependes de permisos Unix, prefiere $HOME (sistema de archivos Linux).
Mantén /mnt/c para interoperabilidad e intercambio ocasional de archivos, no como tu motor de ejecución.
4) ¿Por qué funciona desde el terminal WSL pero falla cuando lo lanza Windows?
Diferente directorio de trabajo, diferentes variables de entorno, diferentes reglas de comillas y a veces diferente traducción de rutas.
Los lanzadores de Windows a menudo inician WSL en un directorio por defecto que no esperabas.
5) ¿Cuál es la forma más segura de pasar una ruta de Windows a WSL?
Usa wslpath para traducir y luego pon entre comillas el resultado. No sustituyas a mano \ por / y llames a eso ingeniería.
6) ¿Por qué los binarios a veces fallan con “No such file” pero ls los muestra?
Un intérprete ELF o librerías compartidas faltantes pueden lanzar ENOENT en tiempo de exec. Revisa file para la ruta del intérprete y ldd para dependencias faltantes.
7) ¿Las opciones de montaje realmente importan para este error?
Sí. Las opciones de montaje influyen en el mapeo de permisos y en el almacenamiento de metadata. Sin metadata, puedes obtener apariencias “ejecutables” confusas que no reflejan lo que pretendías.
No siempre es la causa directa de ENOENT, pero con frecuencia contribuye a la cadena de confusión.
8) ¿Por qué las rutas con espacios fallan más en WSL?
No fallan “en WSL”. Fallan en shells y en fronteras de interoperabilidad donde las reglas de comillas difieren.
Si pones entre comillas cada ruta, reduces drásticamente la tasa de fallos.
9) ¿Cómo hago para que esto deje de pasar en todo el equipo?
Impone LF en los repos, añade una comprobación de saneamiento rápida que valide shebangs y expectativas de ruta, estandariza la configuración de montajes WSL y elige una ubicación de ejecución bendecida (sistema de archivos Linux).
Además: registra rutas absolutas en scripts de build. Depurar sin rutas es como responder a incidentes sin marcas de tiempo.
10) ¿WSL es el problema o mis scripts?
Usualmente tus scripts. WSL solo te da más formas de combinar por accidente supuestos de Windows y semántica de Linux en una sola línea de comandos.
Trata el límite como un salto de red: valida, normaliza y registra.
Chiste 2: Si tu build depende de rutas sin comillas, no tienes una pipeline—tienes una novela de suspense.
Siguientes pasos que puedes hacer esta semana
- Añade una puerta para shebang y finales de línea: un paso de CI que rechace CRLF en scripts ejecutables e imprima la línea ofensora.
- Elige una política “aquí se ejecuta el build”: o en el sistema de archivos Linux (
$HOME) o en el sistema Windows; documenta las compensaciones y aplica consistencia. - Estandariza
/etc/wsl.conf: asegura que las opciones de montaje (especialmentemetadata) sean consistentes entre máquinas de desarrollo si ejecutas desde/mnt/c. - Haz las rutas aburridas: evita puntuación Unicode y confía en nombres ASCII para archivos críticos en automatización.
- Registra rutas absolutas: cada punto de entrada de build debe imprimir
pwd -Py el directorio de script resuelto antes de hacer cualquier cosa destructiva.
El mensaje “No such file or directory” no está equivocado. Solo no te dice qué archivo no puede encontrar.
Una vez que empieces a revisar intérpretes, tipos de montaje y fronteras de interoperabilidad en ese orden, el error deja de ser un misterio y se convierte en un elemento de lista de verificación.