Script para cambiar el directorio actual (cd, pwd)

44

Quiero ejecutar un script para simplemente cambiar el directorio de trabajo actual:

#!/bin/bash
cd web/www/project

Pero, después de ejecutarlo, ¡el pwd actual permanece sin cambios! ¿Cómo puedo hacer eso?

Sony Santos
fuente

Respuestas:

63

Es un comportamiento esperado, y ya se discutió varias veces.

El script se ejecuta en un subshell y no puede cambiar el directorio de trabajo del shell principal. Sus efectos se pierden cuando termina.

Para cambiar el directorio de forma permanente, debe obtener el script, como en

. ./script
enzotib
fuente
8
@ Sony: tenga en cuenta que debe usar returnpara escapar de un script generado de esta manera, no exit, son como funciones de shell y exitsaldrán del shell que originó el script.
Charles Stewart
@CharlesStewart De hecho, no estoy familiarizado con los scripts de origen. ¡Gracias!
Sony Santos
55
es source ./scriptlo mismo?
amyassin
2
@amyassin: sí, lo es
enzotib
2
1. .y sourceson iguales en bash. 2. no necesitamos usar ./antes del nombre del archivo si está en el mismo directorio. Está bien ejecutar solo esto:. script
sobi3ch
19

Para tareas pequeñas como esta, en lugar de crear un script, cree un alias como este,

$ alias cdproj='cd /dir/web/www/proj'

Debe agregar esto a su .bashrcarchivo, si desea que se configure para cada shell interactivo.

Ahora puedes ejecutar esto como $ cdproj.

Sachin Divekar
fuente
1
También puede hacer que el script repita los comandos que se ejecutarán, y luego usar eval `./script` o eval $(./script)ejecutar esos comandos. Este es un enfoque común para los comandos que necesitan actualizar el entorno del shell de invocación.
Keith Thompson
2
Solo tenga mucho cuidado con lo que genera si va a evaladoptar el enfoque.
jw013
13

Usar exec bashal final

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

Sin embargo, esta pregunta a menudo se hace porque uno quiere quedarse en el 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 ejecute una instancia de bash secundaria al final del script:

#!/usr/bin/env bash
cd desired/directory
exec bash

Esto crea una nueva subshell. Escriba exitpara volver al primer shell donde se inició inicialmente el script.

Serge Stroobandt
fuente
Es mejor simplemente obtener el script, como en la respuesta aceptada: el uso execgeneralmente se considera el último recurso de un sinvergüenza .. :)
neuronet
1
Este truco no funciona en Debian 9 Stretch.
vdegenne
3
¡Esta es la forma incorrecta de hacerlo!
Dennis Williamson
44
Como nadie ha detallado los problemas con esto (te estoy mirando, @Dennis): (1) Cada vez que ejecutas esto, se crea un nuevo proceso persistente de bash. Hazlo diez o veinte veces en una sesión, y tendrás entre 11 y 21 procesos bash apilados. Esto puede afectar el rendimiento y, si intenta terminar la sesión limpiamente escribiendo exit(o Ctrl + D), tendrá que hacerlo de 11 a 21 veces. (2) Otro inconveniente de usar un script ejecutable es que, si configura alguna opción de shell (p. Ej.,  dotglobO  globstar) en su sesión de shell interactivo, las perderá porque está comenzando un nuevo shell.
G-Man dice 'reinstalar a Monica' el
1
Muy buena solución! He reescrito mi alias en bash_profile, así que ahora es un script almacenado en un archivo separado. Utilizo el script para ir a una carpeta temporal recién creada. Y ahora es aún más fácil tener una sesión de bash temporal. SRP en acción! ¡Gracias!
artyom.razinov
8

Si bien hay respuestas que realizan la acción exacta que desea, un método más estándar para tal propósito es crear un enlace simbólico:

ln -s ~/web/www/project proj   #use full path to dir!

Entonces podría cdal directorio usando el nombre proj:

cd proj

Este método es más flexible porque puede acceder a los archivos usando el nombre corto sin cd:

ls proj/   #note the endslash!
vim proj/file.x
corvinus
fuente
4

Si cambia entre directorios muy lejos en el sistema de archivos. Recomendaré autojump .

stnly
fuente
4

Depende de lo que vaya a hacer, otra solución puede ser crear una función en lugar de un script.

Ejemplo:

Cree una función en un archivo, digamos /home/aidin/my-cd-script:

function my-cd() {
  cd /to/my/path
}

Luego inclúyalo en su archivo bashrco zshrc:

# Somewhere in rc file
source /home/aidin/my-cd-script

Ahora puedes usarlo como un comando:

$ my-cd
Ayuda en
fuente
0

¿Por qué no usar "exec" que parece hacer exactamente lo que deseo?

#!/bin/bash

cd someplace
exec bash

~/someplace
Pablo
fuente
1
Tenga cuidado con las cosas que parecen ser lo que quiere. (¡Un caballo de madera gigante! ¡Justo lo que quería!) Cada vez que ejecutas esto, se crea un nuevo y persistente proceso de golpe. Hazlo diez o veinte veces en una sesión, y tendrás de 11 a 21 procesos bash apilados. Esto puede afectar el rendimiento y, si intenta finalizar la sesión limpiamente escribiendo exit(o Ctrl + D), tendrá que hacerlo de 11 a 21 veces.
G-Man dice 'reinstalar a Monica' el
Definitivamente pude ver dónde sería un problema. Para mí, lo estoy usando una vez, haciendo el trabajo que necesito y luego saliendo. Si ese es el único inconveniente, puedo vivir con eso. Por otro lado, si hay una solución mejor, estoy dispuesto a analizarla.
Paul
La respuesta de Aidin a esta pregunta , usando una función de shell, y la respuesta de Sachin Divekar , usando un alias, son (IMO) mejores soluciones que usar un script. PD Otro inconveniente de usar un script es que, si configuras opciones de shell (por ejemplo,  dotglobo  globstar), las perderás porque estás comenzando un nuevo shell. … (Continúa)
G-Man dice 'Restablecer a Mónica' el
(Continuación) ... PPS Acabo de notar que usted es, básicamente, reiterando la respuesta de Serge Stroobandt y diciendo '' ¿Por qué no hacer esto? '' A  Pila Cambio esperamos respuestas para proporcionar nuevas ideas y / o información, y no sólo discutir Otras respuestas.
G-Man dice 'restablecer a Mónica' el
-1

Puede hacerlo usando una función o usando &&. Los siguientes ejemplos instalan Zabbix y crean un archivo con una línea dentro.

Ex:

#!/bin/bash

# Create Function:
installZabbix(){
    cd /usr/src/zabbix-4.2.4;
    ./configure --enable-agent;
    make install;
    cd /usr/src/;
    >file;
    echo "Hi, this is a file." >>file;
}

# Call the function:
installZabbix

o:

#!/bin/bash
cd /usr/src/zabbix-4.2.4 && ./configure --enable-agent && make install && cd /usr/src && >file && echo "Hi, this is a file." >>file
Raúl Chiarella
fuente