为什么在bash脚本中不使用两个cd命令执行第二个命令?


15

我编写了一个bash脚本,该脚本创建了一系列目录并将一个项目克隆到所选目录中。

为此,我需要访问cd每个目录(project 1project 2),但是脚本不需要cd访问第二个目录,也不执行命令。

而是cdproject2目录克隆后停止。为什么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
嗨LeonidMew。抱歉,我不知道如何接受答案。不过,两个答案都一样好。
詹妮

5
@Jenny,别着急。阅读有人回答我的问题时该怎么办?相反,当你满意时采取相应的行动。慢慢来,没有理由赶时间。如果您决定是一天,一周还是任何时间,这是完全可以的。
PerlDuck

2
@LeonidMew距问题被问到已经不到45分钟,等待的时间更长,可以,甚至可能会得到更好的答案(就像PerlDuck的评论说的那样,它只是在我键入时弹出的)
Xen2050

6
我很好奇您打算exec bash做什么。
暂停,直到另行通知。

Answers:


28

罪魁祸首是您exec bash在某些职能中的发言。这种exec说法有点怪异,一开始并不容易理解。这意味着:从此处开始,执行以下命令,而不是当前正在运行的command / shell / script。也就是说:它的实例替换当前的shell脚本(就您而言),bash并且它永不返回。

您可以尝试使用shell发行

exec sleep 5

这将用bash命令替换您当前的外壳程序(the ),sleep 5 并且当该命令返回时(5秒后),您的窗口将关闭,因为外壳程序已被替换sleep 5

与脚本相同:如果将exec something脚本放入脚本中,则该脚本将替换为,something并且当something脚本停止执行时,整个脚本将停止。

只需删除exec bash语句即可。


2
@Jenny很高兴听到。轶事:Perl语言也有一个exec具有相同行为的语句,如果你把一些语句exec声明(像exec something; print "This won't run";),那么Perl会警告你print的语句将永远不会得到执行。
PerlDuck

9
BTW恭喜您在cd之后使用&&(如果您不使用set -e)。我已经看到代码像cd tmp; rm -rf *失败一样可怕
eckes

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

确保有相等pushdpopd命令。


2
我不确定您是否已阅读或理解问题空间。这些命令都不会对用户有帮助。
管道

我无处读懂在shell中执行某些命令的必要性。所以我以为他叫bash回到了开始目录。如果您坚持认为,您可能会说:他问了缺少连续性的原因,其他答案都很好地回答了这个问题。
Bernd Wilkeπφ19年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.