¿Por qué no funciona "cd" en un script de shell?

43

Solo quiero escribir un script que cambie mi directorio .

Puse los siguientes comandos en el archivo /home/alex/pathABC

#!/bin/sh
cd /home/alex/Documents/A/B/C
echo HelloWorld

Lo hice chmod +x pathABC.

En la terminal, mientras /home/alexestoy en , ejecuto ./pathABC, pero la salida es justa HelloWorldy el directorio actual no cambia.

Entonces, ¿qué está mal?

Mohammad Reza Rezwani
fuente

Respuestas:

74

Como otros han explicado, el directorio cambia en el proceso secundario de su script, no en el proceso terminal desde el que se llama el script. Después de que el proceso secundario muere, estás de vuelta en la terminal que queda donde estaba.

Varias alternativas:

1. Enlace simbólico

Ponga un enlace simbólico en su hogar al largo camino al que desea acceder fácilmente

$ ln -s /home/alex/Documents/A/B/C ~/pathABC

luego acceda al directorio con:

$ cd ~/pathABC

2. Alias

Pon un alias en tu ~ / .bashrc:

alias pathABC="cd /home/alex/Documents/A/B/C"

(desde aquí )

3. Función

Cree una función que cambie el directorio, la función se ejecuta en el proceso de su terminal y luego puede cambiar su directorio.

(desde aquí )

4. Evite correr como niño

Obtenga su script en lugar de ejecutarlo. El aprovisionamiento (hecho por .o source) hace que el script se ejecute en el mismo shell en lugar de ejecutarse en su propio subshell.

$ . ./pathABC

(de aquí y de aquí )

5. vars compatibles con cd

Establezca la cdable_varsopción en su ~/.bashrcy cree una variable de entorno en el directorio:

shopt -s cdable_vars
export pathABC="/home/alex/Documents/A/B/C"

Entonces puedes usar cd pathABC

(desde aquí )

Gauthier
fuente
15
Ahora entiendo el uso de source! Siempre me pregunté por qué lo hago source .bashrcy nobash .bashrc
hytromo
La opción 3 funcionó muy bien. Acabo de definir una función go_to_wherever () {cd mi / directorio} al comienzo de mi script. Lo llamó antes de ejecutar las operaciones en ese directorio.
i2097i
> 5. vars con capacidad de cd - ¿no es así cd $pathABC?
loxaxs
7

Cuando ejecuta un script en una terminal, se ejecuta un proceso secundario. En este programa secundario, es decir, su script cambiará a cualquier directorio especificado. Pero en el proceso padre, es decir, donde ejecuta el script, todavía está en la ruta anterior. O simplemente podemos decir:

The scope of cd command is only for child process not parent

Tingrammer
fuente
2
Además de esto, @alex para lograr el efecto que está buscando, ejecute el script dentro del proceso padre al obtenerlo: ya sea . pathABCo source pathABC.
zwets
4

Estás cometiendo un error de pensamiento. Mientras el shell actual permanece en el mismo directorio, el script se ha movido al nuevo directorio.

Puede ver eso creando otro script en el nuevo directorio y ejecutándolo desde su script, después de que haya cambiado el directorio:

#!/bin/sh
cd /home/alex/Documents/A/B/C && ./another_script.sh # (if it is executable)

El segundo script se ejecutará desde el nuevo directorio.

HelloWorld 

es solo la salida del script.

Jacob Vlijm
fuente
3
HelloWorld no se "devuelve" al shell principal, se envía a la salida estándar
Mog
Podría ser más claro si solo se ejecuta pwden el nuevo directorio, en lugar de agregar un script completamente nuevo a la situación.
wjandrea
0

Como hello world es solo una declaración de rastreo, intentemos esto:

Cree un archivo de script bash que cd.shcontenga:

#!/bin/bash
echo "/home/mike/Documents/A/B/C"
  • La .shextensión es una convención anterior de dar una extensión a los nombres de archivo de script bash. Es puramente cosmético y generalmente innecesario. Sin embargo, en este caso es importante diferenciarse del cdcomando central .

Marque el archivo ejecutable del script bash usando:

chmod a+x cd.sh

Ahora ejecuta el archivo:

$ cd $(./cd.sh)
bash: cd: /home/alex/Documents/A/B/C: No such file or directory
  • cd todos sabemos.
  • $(...) ejecuta el comando dentro del paréntesis y devuelve la salida.
  • Si cd.shestaba en su camino, no necesita especificar dónde está. Prefijos con ./para especificar que el comando está en el directorio actual.
  • El echoresultado del cd.shscript se envía de vuelta al padre a través de $(...). El padre (nuestro indicador de comandos de shell) usa esta salida y la pasa al cdcomando Linux .

Como otros han mencionado, un proceso secundario no puede cambiar el directorio de los padres. Esta es una forma en que el niño puede decirle al padre a dónde ir después de que finalice el proceso.

WinEunuuchs2Unix
fuente
@wjandrea ¡Eso es lo que obtienes por codificar en un teléfono! Acabo de llegar a casa, lo arreglaré. Gracias. Um acaba de comprobar y funciona bien. ¿Quizás es tu 14.04versión que leí hace aproximadamente una hora?
WinEunuuchs2Unix
Bueno, cambiaste totalmente el guión. Anteriormente era solo un comando: cd /home/mike/Documents/A/B/Cque no producía ningún resultado. Ahora es echo "/home/mike/Documents/A/B/C", lo que produce salida.
wjandrea
@wjandrea Cierto, también cambié totalmente la forma de llamar al script también. En lugar de un simple ./cd.sh, ahora es cd $(./cd.sh)pero cumple el objetivo de que el niño cambie el directorio actual del padre. Sí, no es convencional, pero es otra forma de hacerlo que espero que la gente encuentre interesante.
WinEunuuchs2Unix