从Bash脚本更改当前目录

时间:2009-05-17 11:58:02

标签: bash environment

是否可以从脚本中更改当前目录?

我想在Bash中为目录导航创建一个实用程序。我创建了一个如下所示的测试脚本:

#!/bin/bash
cd /home/artemb

当我从Bash shell执行脚本时,当前目录不会更改。是否可以从脚本中更改当前的shell目录?

15 个答案:

答案 0 :(得分:196)

启动脚本时,会创建一个仅继承环境的新流程。当它结束时,它结束。您当前的环境保持不变。

相反,你可以像这样开始你的脚本:

. myscript.sh

.将评估当前环境中的脚本,因此可能会更改

答案 1 :(得分:156)

您需要将脚本转换为shell函数:

#!/bin/bash
#
# this script should not be run directly,
# instead you need to source it from your .bashrc,
# by adding this line:
#   . ~/bin/myprog.sh
#

function myprog() {
  A=$1
  B=$2
  echo "aaa ${A} bbb ${B} ccc"
  cd /proc
}

原因是每个进程都有自己的当前目录,当您从shell执行程序时,它将在新进程中运行。标准的“cd”,“pushd”和“popd”内置于shell解释器,以便它们影响shell进程。

通过使程序成为shell函数,您将添加自己的进程内命令,然后任何目录更改都会反映在shell进程中。

答案 2 :(得分:52)

鉴于答案的不可读性和过度复杂性,我相信这是请求者应该做的事情

  1. 将该脚本添加到PATH
  2. 将脚本作为. scriptname
  3. 运行

    .(点)将确保脚本不在子shell中运行。

答案 3 :(得分:37)

将上述内容放在一起,您可以创建一个别名

alias your_cmd=". your_cmd"

如果你不想写前导“。”每一次 您希望将脚本源代码发送到shell环境, 或者如果你根本不想记住那必须要做 让脚本正常工作。

答案 4 :(得分:30)

如果您使用bash,可以尝试使用别名:

进入.bashrc文件中添加以下行:

alias p='cd /home/serdar/my_new_folder/path/'

当您在命令行上写“p”时,它将更改目录。

答案 5 :(得分:16)

如果你运行一个bash脚本,那么它将在当前环境或其子环境中运行,而不是在父环境中运行。

如果目标是运行您的命令: goto.sh / home / test 然后以/ home / test交互式工作,一种方法是在脚本中运行bash交互式子shell:

#!/bin/bash
cd $1
exec bash

这样你将进入/ home / test,直到你退出(退出或Ctrl + C)这个shell。

答案 6 :(得分:13)

使用 pushd 将当前目录推送到目录堆栈并将其更改为给定目录, popd 将目录放在堆栈顶部并更改为它

pushd ../new/dir > /dev/null
# do something in ../new/dir
popd > /dev/null

答案 7 :(得分:4)

只需转到

yourusername/.bashrc (or yourusername/.bash_profile on MAC) by an editor

并在最后一行旁边添加此代码:

alias yourcommand="cd /the_path_you_wish"

然后退出编辑。

然后输入:

source ~/.bashrc or source ~/.bash_profile on MAC.

现在您可以在终端

中使用: yourcommand

答案 8 :(得分:3)

我制作了一个更改目录的脚本。看看:https://github.com/ygpark/dj

答案 9 :(得分:3)

基本上我们使用cd..从每个目录返回。我想通过给出你需要一次回来的目录数量来让它变得更容易。您可以使用alias命令使用单独的脚本文件来实现此目的。例如:

<强> code.sh

#!/bin/sh
 _backfunc(){
 if [ "$1" -eq 1 ]; then
  cd ..
 elif [ "$1" -eq 2 ]; then
  cd ../..
 elif [ "$1" -eq 3 ]; then
  cd ../../..
 elif [ "$1" -eq 4 ]; then
  cd ../../../..
 elif ["$1" -eq 10]; then
  cd /home/arun/Documents/work
 fi
 }
alias back='_backfunc'   

在当前shell中使用source code.sh后,您可以使用:

$back 2 

从当前目录返回两步。在here上详细解释。在那里还解释了如何将代码放在〜/ .bashrc中,以便每个打开的新shell都会自动拥有这个新的别名命令。您可以通过添加更多if conditions和不同参数来修改代码,从而添加新命令以转到特定目录。您也可以从here上的git中提取代码。

答案 10 :(得分:0)

这种方法对我来说更容易。

假设在您是管理员的个人iMac上,在打开命令窗口的默认目录下,/ Users / jdoe,这将是要转到的目录:/ Users / jdoe / Desktop / Mongo / db。 3.2.1 / bin中。

这些是可以完成工作的步骤:

  1. vi mongobin,我输入了: cd /Users/jdoe/Desktop/Mongo/db.3.2.1/bin作为第一行。
  2. chmod 755 mongobin
  3. source mongobin
  4. pwd
  5. 瞧!

答案 11 :(得分:0)

我喜欢在不启动新shell的情况下为不同的项目做同样的事情。

在你的情况下:

cd /home/artemb

将the_script保存为:

echo cd /home/artemb

然后用:

启动它
\`./the_script\`

然后使用相同的shell到达目录。

答案 12 :(得分:0)

我还创建了一个名为goat的实用程序,您可以使用它来更轻松地进行导航。

您可以在GitHub上查看源代码。

v2.3.1开始,usage overview看起来像这样:

{{1}}

答案 13 :(得分:0)

在shellscript的cd行下方添加以下内容:

exec $SHELL

答案 14 :(得分:0)

这是我目前用于bash的方法(已在Debian上测试)。也许有更好的方法:

请勿使用exec bash进行操作,例如:

#!/bin/bash
cd $1
exec bash

因为它似乎可以正常工作 您运行它并且脚本完成了,是的,您将处于正确的状态 目录,但您将位于子外壳中,可以通过以下方式确认 然后按Ctrl + D,您会看到它退出了子外壳, 让您回到原始目录。

这通常不是您希望脚本用户留在之后的状态 他们运行的脚本返回,因为并不清楚它们在 一个子外壳,现在它们基本上在打开两个外壳时 以为他们只有一个。他们可能会继续使用此子外壳而没有意识到,这可能会带来意想不到的后果。

如果您确实要退出脚本,并在 新目录,最好更改PS1变量,这样 脚本用户具有视觉指示器,表明他们仍然具有子外壳 打开。

这是我想出的一个例子。它是两个文件,您直接调用一个external.sh, 还有一个internal.sh,它是在outer.sh脚本中获取的。外层 脚本设置两个变量,然后获取内部脚本,以及 之后,它回显两个变量(第二个变量刚刚 由内部脚本修改)。之后,它会临时复制 当前用户的〜/ .bashrc文件,为PS1变量添加替代 在其中,以及清理例程,最后运行exec bash --rcfile指向.bashrc.tmp文件,以使用修改后的环境(包括修改后的提示和清除)初始化bash 常规。

external.sh退出后,您将在可视化目录下被留在所需目录(在本例中为testdir /,由inner.sh脚本输入)的子shell中。 指示器让您清楚知道,如果您退出子外壳, .bashrc.tmp文件将被清理例程删除,您将回到开始的目录中。

也许有更聪明的方法可以做到这一点,但这是我能做到的最好方法 找出大约40分钟的实验时间:

文件1:outer.sh

#!/bin/bash

var1="hello"
var2="world"

source inner.sh

echo $var1
echo $var2

cp ~/.bashrc .bashrc.tmp

echo 'export PS1="(subshell) $PS1"' >> .bashrc.tmp

cat <<EOS >> .bashrc.tmp
cleanup() {
    echo "cleaning up..."
    rm .bashrc.tmp
}

trap 'cleanup' 0
EOS

exec bash --rcfile .bashrc.tmp

文件2:inner.sh

cd testdir
var2="bird"

然后运行:

$ mkdir testdir
$ chmod 755 outer.sh

$ ./outer.sh

它应该输出:

hello
bird

,然后使用exec bash将您放到您的子shell中,但要使用 修改后的提示,使之显而易见,类似于:

(subshell) user@computername:~/testdir$

,如果您在子shell之外按Ctrl-D,则应通过删除来清除它 testdir /目录中的一个临时.bashrc.tmp文件

我想知道是否有比复制.bashrc文件更好的方法 就像那样,尽管要在子外壳中正确更改PS1 var ...