Cambiar el directorio actual de un script Bash

190

¿Es posible cambiar el directorio actual de un script?

Quiero crear una utilidad para la navegación de directorios en Bash. He creado un script de prueba que se parece a lo siguiente:

#!/bin/bash
cd /home/artemb

Cuando ejecuto el script desde el shell Bash, el directorio actual no cambia. ¿Es posible cambiar el directorio de shell actual de un script?

artemb
fuente
2
Solo una sugerencia de mejora: si usa pushd(posiblemente redirigido a >/dev/nullpara suprimir su salida) en lugar de cd, puede volver al directorio anterior con popd.
mklement0

Respuestas:

173

Necesita convertir su script a una función de shell:

#!/bin/bash
#
# this script should not be run directly,
# instead you need to source it from your .bashrc,
# by adding this line:
#   . ~/bin/myprog.sh
#

function myprog() {
  A=$1
  B=$2
  echo "aaa ${A} bbb ${B} ccc"
  cd /proc
}

La razón es que cada proceso tiene su propio directorio actual, y cuando ejecuta un programa desde el shell, se ejecuta en un nuevo proceso. Los estándares "cd", "pushd" y "popd" están integrados en el intérprete de shell para que afecten el proceso de shell.

Al hacer que su programa sea una función de shell, está agregando su propio comando en proceso y luego cualquier cambio de directorio se refleja en el proceso de shell.

Winden
fuente
2
¿Cómo harías esto en tcsh?
joedborg
44
+1. Una cosa que noté fue en el archivo, tenemos que definir la función antes de llamarla. Podría ayudar a alguien tan inexperto como yo.
Bhushan
¿Cuál es la gran diferencia entre definir una función y crear un alias?
HelloGoodbye
1
Una vez que creé este archivo myprog.sh y lo agregué al .bashrc, ¿cómo ejecuto el script? ¿Debo llamar a mi función desde otro archivo de shell o directamente desde el shell? Parece que no funciona de ninguna manera ...
Andrea Silvestri
1
@AndreaSilvestri O bien cierre sesión y vuelva a iniciar sesión o busque .bashrc. Agregarlo a .bashrc no hace nada hasta que se ejecute .bashrc.
Jon Strayer
214

Cuando inicia su script, se crea un nuevo proceso que solo hereda su entorno. Cuando termina, termina. Su entorno actual se mantiene como está.

En su lugar, puede iniciar su secuencia de comandos de esta manera:

. myscript.sh

La .evaluará la secuencia de comandos en el entorno actual, por lo que podría ser alterado

Norbert Hartl
fuente
44
+1 porque tienes razón. Aunque dudo sinceramente que quiera obtener un script de cambio de directorio cada vez que lo necesite. Además, las .shextensiones son totalmente eww. No los uses.
lhunath
1
Sí, generalmente es mejor no usarlo de esa manera. La mayoría de las veces te alegra que tu entorno actual no sufra. Pero luego tengo scripts para hacer algunas tareas de configuración, incluido el cambio al lugar correcto y luego a mí. ellos tambien. Por cierto. .sh es, por supuesto, una cuestión de estilo personal. Probablemente no lo usaría mientras instalo scripts en todo el sistema. Pero en mi ~ / bin los uso para saber qué es qué :)
Norbert Hartl
11
@lhunath ¿Por qué las extensiones .sh son totalmente eww?
Carl Pritchett
1
@CarlPritchett Extensiones de nombre de comando consideradas dañinas .
gniourf_gniourf
1
Para mí, el razonamiento en ese artículo es falso. Parece que el resultado se conoce de antemano, pero encontrar razones no fue tan fácil. Así que mantengo mi punto de vista, es una cuestión de estilo personal, nada más.
Norbert Hartl
55

A la luz de la ilegibilidad y la complicación excesiva de las respuestas, creo que esto es lo que el solicitante debe hacer

  1. agregue ese script a la PATH
  2. ejecuta el script como . scriptname

El .(punto) se asegurará de que el script no se ejecute en un shell secundario.

Steven Penny
fuente
38

Poniendo todo lo anterior junto, puedes hacer un alias

alias your_cmd=". your_cmd"

si no quieres escribir el "" principal cada vez que desee obtener su script para el entorno de shell, o si simplemente no desea recordar que debe hacerse para que el script funcione correctamente.

MergerMan
fuente
¿Esto se mantendrá persistente durante los reinicios?
SDsolar
1
@SDsolar Debe agregar esto a su archivo ~ / .bashrc para que sea persistente. Funciona como un encanto para mí.
Rafał G.
Se puede poner en ~ / .bash_aliases
Champ
@Champ ~/.bash_aliasesno siempre se obtiene cuando se inicia Bash.
Mateusz Piotrowski el
31

Si está utilizando bash, puede probar alias:

en el archivo .bashrc agregue esta línea:

alias p='cd /home/serdar/my_new_folder/path/'

cuando escribe "p" en la línea de comando, cambiará el directorio.

akarca
fuente
1
+1 para alias. la función de shell es interesante, pero el OP solicitó una navegación simple con cd. Supongo que la mayoría de la gente necesita un script como este para navegar por las ramas del código fuente y para ese alias es suficiente
Brad Dre
19

Si ejecuta un script bash, funcionará en su entorno actual o en el de sus hijos, nunca en el padre.

Si el objetivo es ejecutar su comando: goto.sh / home / test Luego trabajar de forma interactiva en / home / test, una forma es ejecutar un subshell interactivo bash dentro de su script:

#!/bin/bash
cd $1
exec bash

De esta manera, estará en / home / test hasta que salga (salir o Ctrl + C) de este shell.

philippe lhardy
fuente
Pensé que esto solucionaría el problema de un script de shell que estaba ejecutando, pero en su lugar, inicia el shell y olvida lo que quería.
vwvan
13

Con pushd, el directorio actual se inserta en la pila de directorios y se cambia al directorio dado, popd obtiene el directorio en la parte superior de la pila y luego cambia a él.

pushd ../new/dir > /dev/null
# do something in ../new/dir
popd > /dev/null
seb
fuente
2
Esto responde a mi pregunta: implementar activamente esta solución con un script de inicio S3 y funciona perfectamente bien. Gracias @seb.
19h
5

Simplemente ve a

yourusername/.bashrc (or yourusername/.bash_profile on MAC) by an editor

y agregue este código al lado de la última línea:

alias yourcommand="cd /the_path_you_wish"

Luego salga del editor.

Luego escriba:

source ~/.bashrc or source ~/.bash_profile on MAC.

ahora puede usar: su comando en la terminal

ThangTD
fuente
3

Básicamente, usamos cd..para volver de cada directorio. Pensé en hacerlo más fácil dando la cantidad de directorios con los que necesita volver a la vez. Puede implementar esto usando un archivo de script separado usando el comando alias. Por ejemplo:

code.sh

#!/bin/sh
 _backfunc(){
 if [ "$1" -eq 1 ]; then
  cd ..
 elif [ "$1" -eq 2 ]; then
  cd ../..
 elif [ "$1" -eq 3 ]; then
  cd ../../..
 elif [ "$1" -eq 4 ]; then
  cd ../../../..
 elif ["$1" -eq 10]; then
  cd /home/arun/Documents/work
 fi
 }
alias back='_backfunc'   

Después de usar source code.shen el shell actual, puede usar:

$back 2 

regresar dos pasos desde el directorio actual. Explicado en detalle por aquí . También se explica allí cómo poner el código en ~ / .bashrc para que cada nuevo shell abierto tenga automáticamente este nuevo comando de alias. Puede agregar un nuevo comando para ir a directorios específicos modificando el código agregando más if conditionsy diferentes argumentos. También puede extraer el código de git aquí .

Arun Chettoor
fuente
Buena solución, para que nunca
arruines
0

Este enfoque es más fácil para mí.

Suponga que en un iMac personal donde es administrador, bajo el directorio predeterminado cuando se abre una ventana de comando, / Users / jdoe, este será el directorio para ir a: /Users/jdoe/Desktop/Mongo/db.3.2.1 /compartimiento.

Estos son los pasos que pueden hacer el trabajo:

  1. vi mongobin, en el que entré: cd /Users/jdoe/Desktop/Mongo/db.3.2.1/bincomo la primera línea.
  2. chmod 755 mongobin
  3. source mongobin
  4. pwd

Voila!

Daniel C. Deng
fuente
0

También he creado una utilidad llamada cabra que puedes usar para facilitar la navegación.

Puede ver el código fuente en GitHub .

A partir de v2.3.1, el resumen de uso se ve así:

# Create a link (h4xdir) to a directory:
goat h4xdir ~/Documents/dev

# Follow a link to change a directory:
cd h4xdir

# Follow a link (and don't stop there!):
cd h4xdir/awesome-project

# Go up the filesystem tree with '...' (same as `cd ../../`):
cd ...

# List all your links:
goat list

# Delete a link (or more):
goat delete h4xdir lojban

# Delete all the links which point to directories with the given prefix:
goat deleteprefix $HOME/Documents

# Delete all saved links:
goat nuke

# Delete broken links:
goat fix
Mateusz Piotrowski
fuente
0

Me gusta hacer lo mismo para diferentes proyectos sin activar un nuevo shell.

En tu caso:

cd /home/artemb

Guarde the_script como:

echo cd /home/artemb

Luego enciéndelo con:

\`./the_script\`

Luego llegas al directorio usando el mismo shell.

DrGamma
fuente
0

Agregue debajo de la línea de CD en su shellscript esto:

exec $SHELL
Alberto Corella
fuente
0

Declara tu camino:

PATH='/home/artemb'     
cd ${PATH}
m_sam
fuente
0

Simplemente escriba PWDy expórtelo dentro de su script, y el cambio persistirá.

export PWD=/your/desired/directory
Samha '
fuente