Dlaczego użycie dwóch poleceń cd w skrypcie bash nie wykonuje drugiego polecenia?

15

Napisałem skrypt bash, który tworzy serię katalogów i klonuje projekt do wybranych katalogów.

W tym celu muszę przejść cddo każdego katalogu ( project 1i project 2), ale skrypt nie przechodzi cddo drugiego katalogu ani nie wykonuje polecenia.

Zamiast tego zatrzymuje się cdi klonuje w project2katalogu. Dlaczego nie wywołuje cd_project1funkcji w następującym kodzie?

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

Wyjście końcowe:

~/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$
Przędzarka
źródło
3
Rozważ zaakceptowanie jednej z odpowiedzi. Jeśli więcej niż jedna odpowiedź jest rozwiązaniem pytania - zaakceptuj najlepszą i głosuj na inną.
LeonidMew
1
Cześć LeonidMew. Niestety nie mam pojęcia, jak zaakceptować odpowiedzi. Obie odpowiedzi są jednakowo dobre.
Jenny
5
@Jenny, nie czuj się rzucony. Przeczytaj Co powinienem zrobić, gdy ktoś odpowie na moje pytanie? zamiast tego i działaj odpowiednio, gdy będziesz zadowolony . Nie spiesz się, nie ma powodu się spieszyć. Jest całkowicie OK, jeśli zdecydujesz się za dzień, za tydzień lub o dowolnej porze.
PerlDuck
2
@LeonidMew minęło zaledwie 45 minut, odkąd pytanie zostało zadane, czekanie jest w porządku, może nawet przyjść lepsza odpowiedź (jak mówi komentarz PerlDuck, pojawił się podczas pisania)
Xen2050
6
Jestem ciekawy, co zamierzałeś exec bashzrobić.
Wstrzymano do odwołania.

Odpowiedzi:

28

Sprawcy są twoimi exec bashstwierdzeniami w niektórych twoich funkcjach. To execstwierdzenie jest nieco dziwne i przede wszystkim niezrozumiałe. Oznacza to: wykonaj następujące polecenie zamiast aktualnie uruchomionego polecenia / powłoki / skryptu odtąd . To znaczy: zastępuje bieżący skrypt powłoki (w twoim przypadku) instancją bashi nigdy nie zwraca.

Możesz to wypróbować za pomocą powłoki i problemu

exec sleep 5

Spowoduje to zastąpienie bieżącej powłoki (the bash) poleceniem, sleep 5 a gdy polecenie to powróci (po 5 sekundach), okno zostanie zamknięte, ponieważ powłoka została zastąpiona sleep 5.

To samo dotyczy skryptu: jeśli wstawisz exec somethingdo skryptu, skrypt zostanie zastąpiony przez, somethinga gdy to somethingprzerwie wykonywanie, cały skrypt przestanie działać.

Po prostu upuszczenie exec bashinstrukcji powinno wystarczyć .

PerlDuck
źródło
2
@Jenny Miło to słyszeć. Anegdota: język Perl posiada również execoświadczenie o tym samym zachowanie i jeśli umieścić niektóre wypowiedzi po z execoświadczeniem (jak exec something; print "This won't run";), a następnie Perl będzie ostrzegał, że printoświadczenie nigdy nie zostanie wykonany.
PerlDuck
9
BTW gratuluje używania && po cd, (jeśli nie używasz set -e). Widziałem Code jak cd tmp; rm -rf *okropne porażki
eckes
15

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

Kluczowym słowem jest tutaj zamień - jeśli jesteś exec bashw skrypcie, dalsze wykonywanie skryptu nie może nastąpić.

steeldriver
źródło
0

jeśli chcesz powrócić do katalogu, który uruchomiłeś, możesz użyć

cd -

Ale jeśli nie masz pewności, czy cdpolecenie zostało w ogóle wykonane, lepiej byłoby użyć poleceń do umieszczenia katalogów roboczych na stosie:

pushd

i wróć do niego (nawet po wielu zmianach katalogu)

popd

koniecznie mieć równość pushd i popdpolecenia.

Bernd Wilke πφ
źródło
2
Nie jestem pewien, czy przeczytałeś lub zrozumiałeś problematyczne miejsce. Żadne z tych poleceń nie pomoże użytkownikowi.
rura
Nigdzie nie mogę odczytać konieczności wykonywania niektórych poleceń w powłoce. Więc pomyślałem, że wezwał bash, aby wrócić do katalogu startowego. Jeśli nalegasz, możesz powiedzieć: zapytał o przyczynę braku kontynuacji, na co doskonale odpowiadają pozostałe odpowiedzi.
Bernd Wilke z