Чому за допомогою двох команд cd у скрипті bash не виконується друга команда?


15

Я написав сценарій bash, який створює серію каталогів і клонує проект до вибраних каталогів.

Для цього мені потрібно до cdкожного каталогу ( project 1і project 2), але скрипт не переходить cdу другий каталог і не виконує команду.

Натомість він зупиняється після cdта клонування в project2каталозі. Чому вона не викликає cd_project1функцію в наступному коді?

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

Термінальний вихід:

~/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$

3
Подумайте про прийняття однієї з відповідей. Якщо більш ніж одна відповідь є вирішенням питання - прийміть найкращого та голосуйте іншим.
LeonidMew

1
Привіт ЛеонідМью. Вибачте, я не маю уявлення, як приймати відповіді. Обидва відповіді однаково хороші.
Дженні

5
@Jenny, не відчувай себе поспіхом. Прочитайте Що робити, коли хтось відповість на моє запитання? натомість і діяти відповідно, коли ви задоволені . Просто витрачайте час, поспішати немає. Це цілком нормально, якщо ви вирішите через день, тиждень або в будь-який час, який це потребує.
PerlDuck

2
@LeonidMew ледве минуло 45 хвилин, звідки було задано питання, довше чекати - це гаразд, краща відповідь може навіть прийти (як каже коментар PerlDuck, він просто спливав, коли я друкував)
Xen2050

6
Мені цікаво, що ви мали exec bashнамір зробити.
Призупинено до подальшого повідомлення.

Відповіді:


28

Винуватцями є ваші exec bashтвердження в деяких ваших функціях. execЗатвердження трохи дивно і не легко зрозуміти , в першу чергу. Це означає: виконайте наступну команду замість поточно запущеної команди / оболонки / скрипту звідси далі . Тобто: він замінює поточний скрипт оболонки (у вашому випадку) екземпляром bashі ніколи не повертається.

Ви можете спробувати це з оболонкою і оформити

exec sleep 5

Це замінить вашу поточну оболонку (the bash) командою, sleep 5 і коли ця команда повернеться (через 5 секунд), ваше вікно закриється, оскільки оболонку було замінено sleep 5.

Те саме з вашим сценарієм: Якщо ви помістите exec somethingу свій сценарій, сценарій заміняється, somethingі коли це somethingзупиняє виконання, весь сценарій зупиняється.

exec bashПотрібно просто відмовитися від тверджень.


2
@Jenny Приємно чути. Анекдот: The Perl мову також має execзаяву з таким же поведінкою , і якщо ви поклали деякі заяви після з execзаявою (наприклад exec something; print "This won't run";) , то Perl буде попереджати вас про те , що printзаява ніколи не будуть виконані.
PerlDuck

9
BTW вітає використання && після компакт-диска (якщо ви не використовуєте set -e). Я бачив Кодекс як cd tmp; rm -rf *
невдалий

15

Від 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.

Ключове слово тут - замінити - якщо ви exec bashвсередині скрипту, подальше виконання сценарію не може відбутися.


0

якщо ви хочете повернутися до каталогу, який ви розпочали, ви можете використовувати його

cd -

Але якщо ви не впевнені, чи cdвиконувалась команда взагалі, то краще використовувати команди для розміщення робочих каталогів у стек:

pushd

і повернутися до нього (навіть після кількох змін каталогу)

popd

обов'язково мати рівний pushdі popdкоманди.


2
Я не впевнений, що ви прочитали чи зрозуміли простір проблеми. Жодна з цих команд не допоможе користувачеві.
труба

Я ніде не можу прочитати необхідність виконання деяких команд в оболонці. Тому я подумав, що він зателефонував у bash, щоб повернутися у стартовий каталог. Якщо ви наполягаєте, ви можете сказати: він запитав причину відсутнього продовження, на що чудово відповідають інші відповіді.
Bernd Wilke πφ
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.