Warum wird der zweite Befehl nicht mit zwei cd-Befehlen im Bash-Skript ausgeführt?

15

Ich habe ein Bash-Skript geschrieben, das eine Reihe von Verzeichnissen erstellt und ein Projekt in ausgewählte Verzeichnisse klont.

Dafür muss ich cdin jedes Verzeichnis ( project 1und project 2), aber das Skript nicht cdin das zweite Verzeichnis oder führt den Befehl aus.

Stattdessen stoppt es nach dem cdKlonen im project2Verzeichnis. Warum wird die cd_project1Funktion im folgenden Code nicht aufgerufen ?

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

~/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
quelle
3
Erwägen Sie, eine der Antworten zu akzeptieren. Wenn mehr als eine Antwort eine Lösung für eine Frage ist, akzeptieren Sie die beste und stimmen Sie eine andere ab.
LeonidMew
1
Hallo LeonidMew. Entschuldigung, ich habe keine Ahnung, wie ich die Antworten akzeptieren soll. Beide Antworten sind jedoch gleich gut.
Jenny
5
@Jenny, sei nicht gehetzt. Lesen Sie Was soll ich tun, wenn jemand meine Frage beantwortet? Stattdessen und entsprechend handeln, wenn Sie zufrieden sind . Nehmen Sie sich Zeit, es gibt keinen Grund, sich zu beeilen. Es ist vollkommen in Ordnung, wenn Sie sich für einen Tag, eine Woche oder eine beliebige Zeit entscheiden.
PerlDuck
2
@LeonidMew Es sind kaum 45 Minuten vergangen, seit die Frage gestellt wurde. Längeres Warten ist A-OK, eine bessere Antwort könnte kommen (wie PerlDucks Kommentar sagt, es ist gerade aufgetaucht, während ich
getippt habe
6
Ich bin gespannt, was du exec bashdamit vorhast.
Bis auf weiteres angehalten.

Antworten:

28

Die Schuldigen sind Ihre exec bashAussagen in einigen Ihrer Funktionen. Die execAussage ist etwas seltsam und überhaupt nicht leicht zu verstehen. Das bedeutet: Führen Sie den folgenden Befehl anstelle des aktuell ausgeführten Befehls / shell / script aus . Das heißt: Es ersetzt das aktuelle Shell-Skript (in Ihrem Fall) durch eine Instanz von bashund wird nie zurückgegeben.

Sie können dies mit einer Shell und Ausgabe ausprobieren

exec sleep 5

Dadurch wird Ihre aktuelle Shell (die bash) durch den Befehl ersetzt, sleep 5 und wenn dieser Befehl zurückgegeben wird (nach 5 Sekunden), wird Ihr Fenster geschlossen, da die Shell durch ersetzt wurde sleep 5.

Dasselbe gilt für Ihr Skript: Wenn Sie es exec somethingin Ihr Skript einfügen, wird es durch ersetzt, somethingund wenn die somethingAusführung beendet wird, wird das gesamte Skript angehalten.

Einfach die exec bashAnweisungen fallen zu lassen sollte genügen.

PerlDuck
quelle
2
@ Jenny Schön zu hören. Anekdote: Die Perl-Sprache hat auch eine execAnweisung mit dem gleichen Verhalten. Wenn Sie nach einer execAnweisung (wie exec something; print "This won't run";) einige Anweisungen einfügen, warnt Perl Sie, dass die printAnweisung niemals ausgeführt wird.
PerlDuck
9
Übrigens Glückwunsch zur Verwendung von && nach cd (falls Sie es nicht verwenden set -e). Ich habe gesehen, Code wie cd tmp; rm -rf *schrecklich scheitern
eckes
15

Von 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.

Das Schlüsselwort ist " Ersetzen". Wenn Sie sich exec bashinnerhalb eines Skripts befinden, kann keine weitere Skriptausführung erfolgen.

Stahlfahrer
quelle
0

Wenn Sie zu dem Verzeichnis zurückkehren möchten, das Sie gestartet haben, können Sie es verwenden

cd -

Wenn Sie jedoch nicht sicher sind, ob ein cdBefehl überhaupt ausgeführt wurde, sollten Sie die Befehle verwenden, um Arbeitsverzeichnisse auf einem Stapel abzulegen:

pushd

und zurückkehren (auch nach mehreren Verzeichniswechseln)

popd

Stellen Sie sicher, dass Sie Gleichheit pushdund popdBefehle haben.

Bernd Wilke πφ
quelle
2
Ich bin nicht sicher, ob Sie den Problembereich gelesen oder verstanden haben. Keiner dieser Befehle hilft dem Benutzer.
Pipe
Ich kann nirgends die Notwendigkeit lesen, einige Befehle in einer Shell auszuführen. Also dachte ich, er hätte die Bash aufgerufen, um wieder in das Startverzeichnis zu gelangen. Wenn Sie darauf bestehen, könnten Sie sagen: Er fragte nach dem Grund für die fehlende Fortsetzung, was von den anderen Antworten perfekt beantwortet wird.
Bernd Wilke πφ