¿Por qué el uso de dos comandos de CD en el script bash no ejecuta el segundo comando?

15

He escrito un script bash que crea una serie de directorios y clona un proyecto en los directorios seleccionados.

Para eso, necesito cdcada directorio ( project 1y project 2), pero el script no lo hace cden el segundo directorio ni ejecuta el comando.

En cambio, se detiene después cdy clona en el project2directorio. ¿Por qué no llama a la cd_project1función en el siguiente código?

#!/bin/bash
#Get the current user name 

function my_user_name() {        
current_user=$USER
echo " Current user is $current_user"
}

#Creating useful directories

function create_useful_directories() {  
  if [[ ! -d "$scratch" ]]; then
  echo "creating relevant directory"
  mkdir -p /home/"$current_user"/Downloads/scratch/"$current_user"/project1/project2
  else
     echo "scratch directory already exists"
     :
  fi
}

#Going to project2 and cloning 

function cd_project2() {

  cd /home/"$current_user"/Downloads/scratch/"$current_user"/project1/project2 &&
  git clone https://username@bitbucket.org/teamsinspace/documentation-tests.git
  exec bash
}

#Going to project1 directory and cloning 
function cd_project1() {

  cd /home/"$current_user"/Downloads/scratch/"$current_user"/project1/ &&
  git clone https://username@bitbucket.org/teamsinspace/documentation-tests.git
  exec bash

}

#Running the functions  
function main() {

  my_user_name
  create_useful_directories
  cd_project2
  cd_project1    
}
main

Terminal de salida:

~/Downloads$. ./bash_install_script.sh    
Current user is mihi
creating relevant directory
Cloning into 'documentation-tests'...
remote: Counting objects: 125, done.
remote: Compressing objects: 100% (115/115), done.
remote: Total 125 (delta 59), reused 0 (delta 0)
Receiving objects: 100% (125/125), 33.61 KiB | 362.00 KiB/s, done.
Resolving deltas: 100% (59/59), done.
~/Downloads/scratch/mihi/project1/project2$
Jenny
fuente
3
Considere aceptar una de las respuestas. Si más de una respuesta es una solución a una pregunta, acepte la mejor y vote por otra.
LeonidMew
1
Hola LeonidMew Lo siento, no tengo idea de cómo aceptar las respuestas. Sin embargo, ambas respuestas son igualmente buenas.
Jenny
55
@ Jenny, no te apresures. Leer ¿Qué debo hacer cuando alguien responde mi pregunta? en su lugar, actúe en consecuencia cuando esté satisfecho . Solo tómate tu tiempo, no hay razón para apurarte. Está perfectamente bien si decides en un día o en una semana o en el tiempo que sea necesario.
PerlDuck
2
@LeonidMew apenas han pasado 45 minutos desde que se hizo la pregunta, esperar más es A-OK, incluso podría aparecer una mejor respuesta (como dice el comentario de PerlDuck, simplemente apareció mientras escribía)
Xen2050
66
Tengo curiosidad por lo que pretendías exec bashhacer.
Pausado hasta nuevo aviso.

Respuestas:

28

Los culpables son sus exec bashdeclaraciones en algunas de sus funciones. La execdeclaración es un poco extraña y no se entiende fácilmente en primer lugar. Significa: ejecutar el siguiente comando en lugar del comando / shell / script actualmente en ejecución a partir de ahora . Es decir: reemplaza el script de shell actual (en su caso) con una instancia de bashy nunca regresa.

Puede probar esto con un shell y emitir

exec sleep 5

Esto reemplazará su shell actual (the bash) con el comando sleep 5 y cuando ese comando regrese (después de 5 segundos) su ventana se cerrará porque el shell ha sido reemplazado por sleep 5.

Lo mismo con su secuencia de comandos: si coloca exec somethingen su secuencia de comandos, la secuencia de comandos se reemplaza con somethingy cuando eso somethingdetiene la ejecución, se detiene toda la secuencia de comandos.

Simplemente dejar caer las exec bashdeclaraciones debe hacer.

PerlDuck
fuente
2
@ Jenny Es bueno escucharlo. Anécdota: el lenguaje Perl también tiene una execdeclaración con el mismo comportamiento y si coloca algunas declaraciones después de una execdeclaración (como exec something; print "This won't run";), entonces Perl le advertirá que la printdeclaración nunca se ejecutará.
PerlDuck
99
Por cierto, felicidades por usar && después de cd, (si no usa set -e). He visto a Code like cd tmp; rm -rf *fail horrible
eckes
15

De help exec:

exec: exec [-cl] [-a name] [command [arguments ...]] [redirection ...]
    Replace the shell with the given command.

    Execute COMMAND, replacing this shell with the specified program.
    ARGUMENTS become the arguments to COMMAND.  If COMMAND is not specified,
    any redirections take effect in the current shell.

La palabra clave aquí es reemplazar : si está exec bashdentro de una secuencia de comandos, no se puede ejecutar más secuencias de comandos.

conductor de acero
fuente
0

si desea volver al directorio que comenzó, puede usar

cd -

Pero si no está seguro de si un cdcomando se ejecutó, sería mejor usar los comandos para colocar directorios de trabajo en una pila:

pushd

y volver a él (incluso después de múltiples cambios de directorio)

popd

asegúrese de tener igualdad pushdy popdcomandos.

Bernd Wilke πφ
fuente
2
No estoy seguro de que haya leído o entendido el espacio del problema. Ninguno de estos comandos ayudará al usuario.
tubería
En ninguna parte puedo leer la necesidad de ejecutar algunos comandos en un shell. Entonces pensé que llamó a bash para volver al directorio de inicio. Si insiste, podría decir: preguntó por la razón de la continuación que falta, que las otras respuestas responden perfectamente.
Bernd Wilke πφ