Por que o uso de dois comandos cd no script bash não executa o segundo comando?

15

Eu escrevi um script bash que cria uma série de diretórios e clona um projeto para diretórios selecionados.

Para isso, preciso de cdcada diretório ( project 1e project 2), mas o script não faz cdpara o segundo diretório nem executa o comando.

Em vez disso, ele pára cde é clonado no project2diretório Por que não chama a cd_project1função no código a seguir?

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

Saída terminal:

~/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
fonte
3
Considere aceitar uma das respostas. Se mais de uma resposta for uma solução para uma pergunta - aceite a melhor e vote outra em outra.
LeonidMew
11
Olá LeonidMew. Desculpe, não tenho idéia de como aceitar as respostas. Ambas as respostas são igualmente boas.
21919 Jenny
5
@ Jenny, não se sinta apressado. Leia O que devo fazer quando alguém responder à minha pergunta? em vez disso, e aja de acordo quando estiver satisfeito . Basta levar o seu tempo, não há razão para se apressar. Tudo bem se você decidir em um dia ou em uma semana ou em qualquer tempo que for necessário.
PerlDuck
2
@LeonidMew Faz apenas 45 minutos desde que a pergunta foi feita, esperar mais tempo é A-OK, uma resposta melhor pode até aparecer (como o comentário de PerlDuck diz, apenas apareceu enquanto eu estava digitando)
Xen2050
6
Estou curioso para saber o que você pretendia exec bashfazer.
Pausado até novo aviso.

Respostas:

28

Os culpados são suas exec bashdeclarações em algumas de suas funções. A execafirmação é um pouco estranha e não é facilmente compreendida em primeiro lugar. Significa: execute o seguinte comando em vez do comando / shell / script atualmente em execução a partir de agora . Ou seja: ele substitui o script atual do shell (no seu caso) por uma instância de bashe nunca retorna.

Você pode tentar isso com um shell e emitir

exec sleep 5

Isso substituirá seu shell atual (the bash) pelo comando sleep 5 e quando esse comando retornar (após 5 segundos) sua janela será fechada porque o shell foi substituído por sleep 5.

O mesmo com o seu script: se você exec somethinginserir o script, o script será substituído por somethinge, quando isso somethinginterromper a execução, o script inteiro será interrompido.

Simplesmente largar as exec bashdeclarações deve servir.

PerlDuck
fonte
2
@ Jenny É bom ouvir. Anedota: A linguagem Perl também possui uma execdeclaração com o mesmo comportamento e, se você colocar algumas declarações após uma execdeclaração (como exec something; print "This won't run";), o Perl avisará que a printdeclaração nunca será executada.
PerlDuck
9
BTW parabeniza por usar && após o cd, (se você não usar set -e). Eu vi Código como cd tmp; rm -rf *falha horrível
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.

A palavra-chave aqui é substituir - se você estiver exec bashdentro de um script, nenhuma execução adicional poderá ocorrer.

chave de aço
fonte
0

se você quiser retornar ao diretório que você iniciou, poderá usar

cd -

Mas se você não tiver certeza se um cdcomando foi executado, seria melhor usar os comandos para colocar diretórios de trabalho em uma pilha:

pushd

e retorne a ele (mesmo após várias alterações de diretório)

popd

certifique-se de ter equaly pushde popdcomandos.

Bernd Wilke πφ
fonte
2
Não sei se você leu ou entendeu o espaço do problema. Nenhum desses comandos ajudará o usuário.
pipe
Em nenhum lugar posso ler a necessidade de executar alguns comandos em um shell. Então eu pensei que ele ligou para o bash para voltar ao diretório inicial. Se você insistir, poderá dizer: ele perguntou o motivo da continuação perdida, o que é perfeitamente respondido pelas outras respostas.
Bernd Wilke n ° 17/03/19