是否可以从脚本更改当前目录?
我想在Bash中创建一个目录导航实用程序。我创建了一个测试脚本,如下所示:
#!/bin/bash
cd /home/artemb
当我从Bash shell执行脚本时,当前目录不会改变。是否有可能从脚本更改当前shell目录?
是否可以从脚本更改当前目录?
我想在Bash中创建一个目录导航实用程序。我创建了一个测试脚本,如下所示:
#!/bin/bash
cd /home/artemb
当我从Bash shell执行脚本时,当前目录不会改变。是否有可能从脚本更改当前shell目录?
当前回答
我已经做了一个脚本来更改目录。来看看:https://github.com/ygpark/dj
其他回答
这是我目前为bash做这件事的方式(在Debian上测试)。也许有更好的办法:
不要用exec bash这样做,例如:
#!/bin/bash
cd $1
exec bash
because while it appears to work, after you run it and your script finishes, yes you'll be in the correct directory, but you'll be in it in a subshell, which you can confirm by pressing Ctrl+D afterwards, and you'll see it exits the subshell, putting you back in your original directory. This is usually not a state you want a script user to be left in after the script they run returns, because it's non-obvious that they're in a subshell and now they basically have two shells open when they thought they only had one. They might continue using this subshell and not realize it, and it could have unintended consequences. If you really want the script to exit and leave open a subshell in the new directory, it's better if you change the PS1 variable so the script user has a visual indicator that they still have a subshell open. Here's an example I came up with. It is two files, an outer.sh which you call directly, and an inner.sh which is sourced inside the outer.sh script. The outer script sets two variables, then sources the inner script, and afterwards it echoes the two variables (the second one has just been modified by the inner script). Afterwards it makes a temp copy of the current user's ~/.bashrc file, adds an override for the PS1 variable in it, as well as a cleanup routine, and finally it runs exec bash --rcfile pointing at the .bashrc.tmp file to initialize bash with a modified environment, including the modified prompt and the cleanup routine. After outer.sh exits, you'll be left inside a subshell in the desired directory (in this case testdir/ which was entered into by the inner.sh script) with a visual indicator making it clear to you, and if you exit out of the subshell, the .bashrc.tmp file will be deleted by the cleanup routine, and you'll be back in the directory you started in. Maybe there's a smarter way to do it, but that's the best way I could figure out in about 40 minutes of experimenting:
文件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$
如果你用Ctrl-D退出子shell,它应该通过删除来清理 testdir/目录下的临时.bashrc.tmp文件 我想知道是否有比复制.bashrc文件更好的方法 就像这样,在subshell中适当地改变PS1的变量…
你需要把你的脚本转换成一个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进程中。
把上面的内容放在一起,就可以创建一个别名
alias your_cmd=". your_cmd"
如果你不想每次都写开头的"." 你想把你的脚本源到shell环境, 或者如果你只是不想记住,那就必须这么做 脚本才能正确工作。
简单地去
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.
现在你可以在终端中使用:your命令
如果您运行bash脚本,那么它将在其当前环境或其子环境上操作,而不会在父环境上操作。
如果目标是运行命令: goto.sh /home/test 然后在/home/test中交互式地工作,一种方法是在你的脚本中运行一个bash交互式子shell:
#!/bin/bash
cd $1
exec bash
这样,您将处于/home/test中,直到退出(退出或按Ctrl+C)这个shell。