¿Por qué el “cd” no funciona en un script de shell?

Intento escribir un pequeño script para cambiar el directorio actual a mi directorio de proyecto:

#!/bin/bash cd /home/tree/projects/java 

Guardé este archivo como proyecto, agregué permiso de ejecución con chmod y lo copié en /usr/bin . Cuando lo llamo por: proj , no hace nada. ¿Qué estoy haciendo mal?

Los scripts de Shell se ejecutan dentro de una subshell, y cada subshell tiene su propio concepto de lo que es el directorio actual. El cd tiene éxito, pero tan pronto como la subshell se cierra, vuelves a estar en el caparazón interactivo y nada cambia allí.

Una forma de evitar esto es usar un alias en su lugar:

 alias proj="cd /home/tree/projects/java" 

¡No estás haciendo nada mal! Ha cambiado el directorio, pero solo dentro de la subshell que ejecuta el script.

Puede ejecutar la secuencia de comandos en su proceso actual con el comando “punto”:

 . proj 

Pero preferiría la sugerencia de Greg de usar un alias en este caso simple.

El cd en su script funcionaba técnicamente ya que cambiaba el directorio del shell que ejecutaba el script, pero ese era un proceso separado bifurcado desde el shell interactivo.

Una manera compatible con Posix para resolver este problema es definir un procedimiento de shell en lugar de un script de comando invocado por shell.

 jhome () { cd /home/tree/projects/java } 

Puede escribir esto o ponerlo en uno de los varios archivos de inicio del shell.

El cd se hace dentro del shell del script. Cuando el guión finaliza, ese intérprete de comandos sale, y luego queda en el directorio que era. “Fuente” del script, no lo ejecute. En lugar de:

 ./myscript.sh 

hacer

 . ./myscript.sh 

(Observe el punto y el espacio antes del nombre del guión).

Para crear un script bash que se codificará en un directorio de selección:

Crea el archivo de script

 #! / bin / sh
 # file: / scripts / cdjava
 #
 cd / home / askgelal / projects / java

Luego crea un alias en tu archivo de inicio.

 #! / bin / sh
 # file /scripts/mastercode.sh
 #
 alias cdjava = '.  / scripts / cdjava '

  • Creé un archivo de inicio donde descargo todos mis alias y funciones personalizadas.
  • Luego obtengo este archivo en mi .bashrc para tenerlo configurado en cada arranque.

Por ejemplo, cree un archivo maestro de alias / funciones: /scripts/mastercode.sh
(Pon el alias en este archivo)

Luego, al final de su archivo .bashrc :

 fuente /scripts/mastercode.sh


Ahora es fácil de copiar a su directorio java, solo escriba cdjava y usted está allí.

La idea de Jeremy Ruten de usar un enlace simbólico desencadenó un pensamiento que no ha cruzado ninguna otra respuesta. Utilizar:

 CDPATH=:$HOME/projects 

El colon principal es importante; significa que si hay un directorio ‘dir’ en el directorio actual, entonces ‘ cd dir ‘ cambiará a eso, en lugar de saltar a otra parte. Con el valor establecido como se muestra, puede hacer:

 cd java 

y, si no hay un subdirectorio llamado java en el directorio actual, lo llevará directamente a $ HOME / projects / java – sin alias, sin scripts, sin ejecutivos dudosos o comandos de punto.

My $ HOME es / Users / jleffler; mi $ CDPATH es:

 :/Users/jleffler:/Users/jleffler/mail:/Users/jleffler/src:/Users/jleffler/src/perl:/Users/jleffler/src/sqltools:/Users/jleffler/lib:/Users/jleffler/doc:/Users/jleffler/work 

Puedes usar para ejecutar una secuencia de comandos en el entorno de shell actual:

 . script_name 

o alternativamente, es una source alias más legible pero específica para el shell:

 source script_name 

Esto evita la subshell y permite que las variables o los builtins (incluido cd ) afecten al shell actual.

Conseguí mi código para trabajar usando . .

./ dosis no funciona porque no cambia su directorio en el terminal, solo cambia el directorio específico de ese script.

Aquí está mi progtwig

 #!/bin/bash echo "Taking you to eclipse's workspace." cd /Developer/Java/workspace 

Aquí está mi terminal

 nova:~ Kael$ nova:~ Kael$ . workspace.sh Taking you to eclipe's workspace. nova:workspace Kael$ 

Use exec bash al final

Un script bash funciona en su entorno actual o en el de sus hijos, pero nunca en su entorno principal.

Sin embargo, a menudo se hace esta pregunta porque uno quiere que se lo deje en un indicador bash en un determinado directorio después de la ejecución de un script bash desde otro directorio.

Si este es el caso, simplemente ejecuta una instancia child bash al final del script:

 #!/bin/bash cd /home/tree/projects/java exec bash 

simplemente ejecuta:

 cd /home/xxx/yyy && command_you_want 

Cuando activa un script de shell, ejecuta una nueva instancia de dicho shell ( /bin/bash ). Por lo tanto, su script simplemente activa un shell, cambia el directorio y sale. Dicho de otra manera, cd (y otros comandos similares) dentro de un script de shell no afectan ni tienen acceso al shell desde el que se lanzaron.

En mi caso particular, necesitaba demasiadas veces cambiar para el mismo directorio. Entonces en mi .bashrc (uso ubuntu) agregué el

1 –

$ nano ~. / bashrc

  function switchp { cd /home/tree/projects/$1 } 

2-

$ fuente ~ / .bashrc

3 –

$ switchp java

Directamente lo hará: cd / home / tree / projects / java

¡Espero que ayude!

Solo cambia el directorio del script en sí, mientras que su directorio actual permanece igual.

Es posible que desee utilizar un enlace simbólico en su lugar. Le permite hacer un “acceso directo” a un archivo o directorio, por lo que solo debe escribir algo como cd my-project .

Puedes hacer lo siguiente:

 #!/bin/bash cd /your/project/directory # start another shell and replacing the current exec /bin/bash 

EDITAR: Esto podría estar ‘salpicado’ también, para evitar la creación de capas posteriores.

Ejemplo:

 . ./previous_script (with or without the first line) 

Puede combinar un alias y una secuencia de comandos

 alias proj="cd \`/usr/bin/proj !*\`" 

siempre que la secuencia de comandos muestre la ruta de destino. Tenga en cuenta que esos son backticks que rodean el nombre del script.

Por ejemplo, tu script podría ser

 #!/bin/bash echo /home/askgelal/projects/java/$1 

La ventaja de esta técnica es que la secuencia de comandos puede tomar cualquier número de parámetros de línea de comando y emitir diferentes destinos calculados por una lógica posiblemente compleja.

Puede combinar los enfoques de alias y puntos de Adam y Greg para hacer algo que pueda ser más dynamic.

 alias project=". project" 

Ahora, al ejecutar el alias del proyecto, se ejecutará la secuencia de comandos del proyecto en el shell actual en lugar de la subshell.

Puedes usar el operador &&:

cd myDirectory && ls

En su archivo ~ / .bash_profile. agregar la siguiente función

 move_me() { cd ~/path/to/dest } 

Reinicie la terminal y puede escribir

 move_me 

y será movido a la carpeta de destino.

Si bien la búsqueda del script que desea ejecutar es una solución, debe tener en cuenta que este script puede modificar directamente el entorno del shell actual. Además, ya no es posible pasar argumentos.

Otra forma de hacerlo es implementar tu script como una función en bash.

 function cdbm() { cd whereever_you_want_to_go echo "Arguments to the functions were $1, $2, ..." } 

Esta técnica es utilizada por autojump: http://github.com/joelthelion/autojump/wiki para proporcionarle el aprendizaje de los marcadores del directorio de shell.

Esto debería hacer lo que quieras. Cambie al directorio de interés (desde dentro del script) y luego genere un nuevo shell bash.

 #!/bin/bash # saved as mov_dir.sh cd ~/mt/v3/rt_linux-rt-tools/ bash 

Si ejecuta esto, lo llevará al directorio de interés y cuando lo salga lo llevará de vuelta al lugar original.

 root@intel-corei7-64:~# ./mov_dir.sh root@intel-corei7-64:~/mt/v3/rt_linux-rt-tools# exit root@intel-corei7-64:~# 

Esto incluso lo llevará a su directorio original cuando salga ( CTRL + d )

Mucho tiempo después, pero hice lo siguiente:

crea un archivo llamado caso

pegue lo siguiente en el archivo:

 #!/bin/sh cd /home/"$1" 

guárdalo y luego:

 chmod +x case 

También creé un alias en mi .bashrc :

 alias disk='cd /home/; . case' 

ahora cuando escribo:

 case 12345 

esencialmente estoy escribiendo:

 cd /home/12345 

Puede escribir cualquier carpeta después de ‘caso’:

 case 12 case 15 case 17 

que es como escribir:

 cd /home/12 cd /home/15 cd /home/17 

respectivamente

En mi caso, el camino es mucho más largo: estos tipos lo resumieron con la información anterior.

Puede crear una función como la siguiente en su .bash_profile y funcionará sin problemas.

La siguiente función toma un parámetro opcional que es un proyecto. Por ejemplo, solo puedes ejecutar

 cdproj 

o

 cdproj project_name 

Aquí está la definición de la función.

 cdproj(){ dir=/Users/yourname/projects if [ "$1" ]; then cd "${dir}/${1}" else cd "${dir}" fi } 

No te olvides de obtener tu .bash_profile

Si usa pescado como caparazón, la mejor solución es crear una función. Como ejemplo, dada la pregunta original, puede copiar las 4 líneas a continuación y pegarlas en su línea de comando de pez:

 function proj cd /home/tree/projects/java end funcsave proj 

Esto creará la función y la guardará para usarla más tarde. Si su proyecto cambia, simplemente repita el proceso usando la nueva ruta.

Si lo prefiere, puede agregar manualmente el archivo de función haciendo lo siguiente:

 nano ~/.config/fish/functions/proj.fish 

e ingrese el texto:

 function proj cd /home/tree/projects/java end 

y finalmente presione ctrl + x para salir yy seguido de return para guardar sus cambios.

( NOTA: el primer método de uso de funcsave crea el archivo proj.fish para usted ).

Tengo un script bash simple llamado p para administrar el cambio de directorio en
github.com/godzilla/bash-stuff
simplemente coloque el script en su directorio local bin (/ usr / local / bin)
y pon

 alias p='. p' 

en tu .bashrc

No necesita ningún script, solo configure la opción correcta y cree una variable de entorno.

 shopt -s cdable_vars 

en su ~/.bashrc permite cd al contenido de las variables de entorno.

Cree una variable de entorno de este tipo:

 export myjava="/home/tree/projects/java" 

y puedes usar:

 cd myjava 

Otras alternativas

Usando Bash Profile Functions:

Una característica del perfil bash es almacenar funciones personalizadas que se pueden ejecutar en el terminal o en las secuencias de comandos bash de la misma manera que se ejecutan las aplicaciones / comandos. También se puede usar como acceso directo para comandos largos.

Para que su sistema funcione de forma eficiente, necesitará copiar su función al final de varios archivos.

 /home/user/.bashrc /home/user/.bash_profile /root/.bashrc /root/.bash_profile 

Puede sudo kwrite /home/user/.bashrc /home/user/.bash_profile /root/.bashrc /root/.bash_profile para editar / crear esos archivos rápidamente

Ejemplo de script

Hacer acceso directo a cd .. con cdd

 cdd() { cd .. } 

Es un atajo

 ll() { ls -l -h } 

Es un atajo

 lll() { ls -l -h -a } 

Cómo :

Copie su función al final de sus archivos y reinicie su terminal, luego puede ejecutar cdd o cualquiera que sea la función que escribió

Tenga en cuenta la discusión ¿Cómo configuro el directorio de trabajo del proceso principal?

Contiene algunas respuestas hackish, por ejemplo, https://stackoverflow.com/a/2375174/755804 (cambiando el directorio de proceso primario a través de gdb, no lo haga) y https://stackoverflow.com/a/51985735/755804 ( el comando tailcd que inyecta cd dirname a la secuencia de entrada del proceso principal; bueno, idealmente debería ser una parte de bash en lugar de un hack)

Puede ejecutar algunas líneas en la misma subcadena si finaliza líneas con barra invertida.

 cd somedir; \ pwd