[英]Change the current directory from a Bash script
是否可以从脚本更改当前目录?
我想在 Bash 中创建一个用于目录导航的实用程序。 我创建了一个如下所示的测试脚本:
#!/bin/bash
cd /home/artemb
当我从 Bash shell 执行脚本时,当前目录不会改变。 是否有可能从脚本更改当前的 shell 目录?
当您启动脚本时,会创建一个仅继承您的环境的新进程。 当它结束时,它就结束了。 您当前的环境保持原样。
相反,您可以像这样启动脚本:
. myscript.sh
.
将评估当前环境中的脚本,因此它可能会被更改
您需要将脚本转换为 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 进程中。
鉴于答案的不可读性和过于复杂,我认为这是请求者应该做的
PATH
. scriptname
. scriptname
.
(dot) 将确保脚本不在子 shell 中运行。
把上面的放在一起,你可以做一个别名
alias your_cmd=". your_cmd"
如果你不想写前导“.” 每次您想将脚本提供给 shell 环境时,或者如果您只是不想记住必须这样做才能使脚本正常工作。
如果您使用 bash,您可以尝试别名:
在 .bashrc 文件中添加这一行:
alias p='cd /home/serdar/my_new_folder/path/'
当你在命令行上写“p”时,它会改变目录。
如果您运行 bash 脚本,那么它将在其当前环境或其子项上运行,而不是在父项上运行。
如果目标是运行您的命令:goto.sh /home/test 然后在 /home/test 中交互工作,一种方法是在您的脚本中运行 bash 交互式子shell:
#!/bin/bash
cd $1
exec bash
这样,您将在 /home/test 中,直到您退出( exit 或 Ctrl+C )此 shell。
使用pushd将当前目录推送到目录堆栈上,并将其更改为给定目录, popd获取堆栈顶部的目录,然后更改为该目录。
pushd ../new/dir > /dev/null
# do something in ../new/dir
popd > /dev/null
只需转到
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
我已经制作了一个脚本来更改目录。 看一看: https : //github.com/ygpark/dj
基本上我们使用cd..
从每个目录返回。 我认为通过提供您一次需要返回的目录数量来使其更容易。 您可以使用 alias 命令使用单独的脚本文件来实现这一点。 例如:
代码.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
从当前目录返回两步。 在这里详细解释。 那里还解释了如何将代码放在 ~/.bashrc 中,以便每个新打开的 shell 都会自动拥有这个新的别名命令。 您可以通过添加更多if conditions
和不同参数来修改代码,从而添加新命令以转到特定目录。 你也可以从 git 中提取代码到这里。
在您的 shellscript 中添加以下 cd 行:
exec $SHELL
这种方法对我来说更容易。
假设在您是管理员的个人 iMac 上,在打开命令窗口时的默认目录 /Users/jdoe 下,这将是要转到的目录:/Users/jdoe/Desktop/Mongo/db.3.2.1 /斌。
这些是可以完成工作的步骤:
cd /Users/jdoe/Desktop/Mongo/db.3.2.1/bin
作为第一行。chmod 755 mongobin
source mongobin
pwd
瞧!
我喜欢在不启动新 shell 的情况下为不同的项目做同样的事情。
在你的情况下:
cd /home/artemb
将 the_script 保存为:
echo cd /home/artemb
然后启动它:
\`./the_script\`
然后您使用相同的shell 进入该目录。
我还创建了一个名为goat的实用程序,您可以使用它来更轻松地导航。
您可以在GitHub 上查看源代码。
# Create a link (h4xdir) to a directory:
goat h4xdir ~/Documents/dev
# Follow a link to change a directory:
cd h4xdir
# Follow a link (and don't stop there!):
cd h4xdir/awesome-project
# Go up the filesystem tree with '...' (same as `cd ../../`):
cd ...
# List all your links:
goat list
# Delete a link (or more):
goat delete h4xdir lojban
# Delete all the links which point to directories with the given prefix:
goat deleteprefix $HOME/Documents
# Delete all saved links:
goat nuke
# Delete broken links:
goat fix
声明你的路径:
PATH='/home/artemb'
cd ${PATH}
这是我目前为 bash 做的方式(在 Debian 上测试)。 也许有更好的方法:
不要用 exec bash 来做,例如这样:
#!/bin/bash
cd $1
exec bash
因为虽然它看起来可以工作,但在运行它并完成脚本之后,是的,您将位于正确的目录中,但您将位于子shell 中,之后您可以通过按 Ctrl+D 来确认,然后您将看到它退出子shell,将您放回原始目录。
这通常不是您希望脚本用户在他们运行的脚本返回后留下的状态,因为不明显的是,他们处于子 shell 中,现在他们基本上打开了两个 shell,而他们认为只有一个 shell。 他们可能会继续使用这个子 shell 而没有意识到它,这可能会产生意想不到的后果。
如果您真的希望脚本退出并在新目录中打开一个子 shell,最好更改 PS1 变量,以便脚本用户有一个视觉指示器,表明他们仍然打开了一个子 shell。
这是我想出的一个例子。 它是两个文件,一个是直接调用的 outer.sh,另一个是来自于 outer.sh 脚本的inner.sh。 外部脚本设置两个变量,然后获取内部脚本,然后回显这两个变量(第二个变量刚刚被内部脚本修改)。 之后它会制作当前用户的 ~/.bashrc 文件的临时副本,为其中的 PS1 变量添加一个覆盖,以及一个清理例程,最后它运行 exec bash --rcfile 指向 .bashrc.tmp 文件使用修改后的环境初始化 bash,包括修改后的提示和清理例程。
在outer.sh 退出后,您将被留在所需目录(在本例中为 testdir/ 由inner.sh 脚本输入)的子shell 中,并带有一个视觉指示器,让您清楚,如果您退出在子 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$
如果你 Ctrl-D 退出子shell,它应该通过删除 testdir/ 目录中的临时 .bashrc.tmp 文件来清理
我想知道是否有比复制 .bashrc 文件更好的方法,尽管在子外壳中正确更改 PS1 变量...
这是上述答案的简化汇编。
创建一个 shell 文件shellfile.sh
在脚本中更改您在函数内的目录
#!/bin/bash
cd folder1/folder2/
现在运行脚本.
在它之前。
.
使用当前线程/会话来执行脚本。
. shellfile.sh
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.