Pourquoi l'utilisation de deux commandes cd dans le script bash n'exécute-t-elle pas la deuxième commande?

15

J'ai écrit un script bash qui crée une série de répertoires et clone un projet dans des répertoires sélectionnés.

Pour cela, j'ai besoin de cdchaque répertoire ( project 1et project 2), mais le script ne fait pas cdle deuxième répertoire ni n'exécute la commande.

Au lieu de cela, il s'arrête après cdet clonage dans le project2répertoire. Pourquoi n'appelle-t-il pas la cd_project1fonction dans le code suivant?

#!/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

Sortie borne:

~/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
la source
3
Envisagez d'accepter l'une des réponses. Si plusieurs réponses sont une solution à une question - acceptez la meilleure et votez pour une autre.
LeonidMew
1
Salut LeonidMew. Désolé, je ne sais pas comment accepter les réponses. Cependant, les deux réponses sont également bonnes.
Jenny
5
@Jenny, ne te sens pas pressé. Lire Que dois-je faire lorsque quelqu'un répond à ma question? au lieu de cela et agissez en conséquence lorsque vous êtes satisfait . Prenez votre temps, il n'y a aucune raison de se dépêcher. C'est parfaitement OK si vous décidez en une journée ou en une semaine ou en tout temps.
PerlDuck
2
@LeonidMew cela fait à peine 45 minutes que la question a été posée, attendre plus longtemps est A-OK, une meilleure réponse pourrait même arriver (comme le dit le commentaire de PerlDuck, elle est apparue pendant que je
tapais
6
Je suis curieux de savoir ce que vous vouliez exec bashfaire.
pause jusqu'à nouvel ordre.

Réponses:

28

Les coupables sont vos exec bashdéclarations dans certaines de vos fonctions. La execdéclaration est un peu bizarre et difficile à comprendre en premier lieu. Cela signifie: exécutez la commande suivante au lieu de la commande / shell / script en cours d'exécution à partir d'ici . C'est-à-dire: il remplace le script shell actuel (dans votre cas) par une instance de bashet il ne revient jamais.

Vous pouvez essayer cela avec un shell et un problème

exec sleep 5

Cela remplacera votre shell actuel (le bash) par la commande sleep 5 et lorsque cette commande reviendra (après 5 secondes) votre fenêtre se fermera car le shell a été remplacé par sleep 5.

Même chose avec votre script: si vous mettez exec somethingdans votre script, le script est remplacé par somethinget quand cela somethingarrête l'exécution, le script entier s'arrête.

La simple suppression des exec bashdéclarations devrait suffire.

PerlDuck
la source
2
@Jenny Ravi d'entendre. Anecdote: le langage Perl a également une execinstruction avec le même comportement et si vous mettez des instructions après une execinstruction (comme exec something; print "This won't run";) alors Perl vous avertira que l' printinstruction ne sera jamais exécutée.
PerlDuck
9
BTW vous félicite pour l'utilisation de && après le cd (si vous ne l'utilisez pas set -e). J'ai vu Code comme un cd tmp; rm -rf *horrible échec
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.

Le mot clé ici est remplacer - si vous exec bashde l'intérieur d'un script, aucune autre exécution de script ne peut se produire.

tournevis
la source
0

si vous voulez un retour au répertoire que vous avez commencé, vous pouvez utiliser

cd -

Mais si vous n'êtes pas sûr si une cdcommande a été exécutée, il serait préférable d'utiliser les commandes pour placer les répertoires de travail sur une pile:

pushd

et y revenir (même après plusieurs changements de répertoire)

popd

assurez-vous d'avoir equaly pushdet popdcommandes.

Bernd Wilke πφ
la source
2
Je ne suis pas sûr que vous ayez lu ou compris l'espace problématique. Aucune de ces commandes n'aidera l'utilisateur.
pipe
Je ne peux nulle part lire la nécessité d'exécuter certaines commandes dans un shell. J'ai donc pensé qu'il appelait bash pour revenir dans le répertoire de démarrage. Si vous insistez, vous pourriez dire: il a demandé la raison de la suite manquante, ce qui est parfaitement répondu par les autres réponses.
Bernd Wilke du