是否可以从脚本中更改当前目录?
我想在Bash中为目录导航创建一个实用程序。我创建了一个如下所示的测试脚本:
#!/bin/bash
cd /home/artemb
当我从Bash shell执行脚本时,当前目录不会更改。是否可以从脚本中更改当前的shell目录?
答案 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)
鉴于答案的不可读性和过度复杂性,我相信这是请求者应该做的事情
PATH
. scriptname
.
(点)将确保脚本不在子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中。
这些是可以完成工作的步骤:
cd /Users/jdoe/Desktop/Mongo/db.3.2.1/bin
作为第一行。chmod 755 mongobin
source mongobin
pwd
瞧!
答案 11 :(得分:0)
我喜欢在不启动新shell的情况下为不同的项目做同样的事情。
在你的情况下:
cd /home/artemb
将the_script保存为:
echo cd /home/artemb
然后用:
启动它\`./the_script\`
然后使用相同的shell到达目录。
答案 12 :(得分:0)
答案 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分钟的实验时间:
#!/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
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 ...