繁体   English   中英

从 Bash 脚本更改当前目录

[英]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 进程中。

鉴于答案的不可读性和过于复杂,我认为这是请求者应该做的

  1. 将该脚本添加到PATH
  2. 将脚本作为. 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 /斌。

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

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

瞧!

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

在你的情况下:

cd /home/artemb

将 the_script 保存为:

echo cd /home/artemb

然后启动它:

\`./the_script\`

然后您使用相同的shell 进入该目录。

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

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

v2.3.1 开始使用概述如下所示:

# 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 分钟的实验中找到的最好方法:

文件 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 文件更好的方法,尽管在子外壳中正确更改 PS1 变量...

这是上述答案的简化汇编。
创建一个 shell 文件shellfile.sh在脚本中更改您在函数内的目录

#!/bin/bash

cd folder1/folder2/

现在运行脚本. 在它之前。
. 使用当前线程/会话来执行脚本。

. shellfile.sh

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM