从 Bash 脚本更改当前目录

发布于 2024-07-21 07:07:14 字数 197 浏览 7 评论 0原文

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

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

#!/bin/bash
cd /home/artemb

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

Is it possible to change current directory from a script?

I want to create a utility for directory navigation in Bash. I have created a test script that looks like the following:

#!/bin/bash
cd /home/artemb

When I execute the script from the Bash shell the current directory doesn't change. Is it possible at all to change the current shell directory from a script?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(17

梦亿 2024-07-28 07:07:15

我喜欢对不同的项目做同样的事情,而不需要启动新的 shell。

在您的情况下:

cd /home/artemb

将 the_script 保存为:

echo cd /home/artemb

然后使用以下命令启动它:

\`./the_script\`

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

I like to do the same thing for different projects without firing up a new shell.

In your case:

cd /home/artemb

Save the_script as:

echo cd /home/artemb

Then fire it up with:

\`./the_script\`

Then you get to the directory using the same shell.

我的痛♀有谁懂 2024-07-28 07:07:15

声明你的路径:

PATH='/home/artemb'     
cd ${PATH}

Declare your path:

PATH='/home/artemb'     
cd ${PATH}
与往事干杯 2024-07-28 07:07:14

当您启动脚本时,将创建一个仅继承您的环境的新进程。 当它结束时,它就结束了。 您当前的环境保持原样。

相反,您可以像这样启动脚本:

. myscript.sh

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

When you start your script, a new process is created that only inherits your environment. When it ends, it ends. Your current environment stays as it is.

Instead, you can start your script like this:

. myscript.sh

The . will evaluate the script in the current environment, so it might be altered

等风也等你 2024-07-28 07:07:14

您需要将脚本转换为 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 进程中。

You need to convert your script to a shell function:

#!/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
}

The reason is that each process has its own current directory, and when you execute a program from the shell it is run in a new process. The standard "cd", "pushd" and "popd" are builtin to the shell interpreter so that they affect the shell process.

By making your program a shell function, you are adding your own in-process command and then any directory change gets reflected in the shell process.

鱼窥荷 2024-07-28 07:07:14

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

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

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

In light of the unreadability and overcomplication of answers, i believe this is what the requestor should do

  1. add that script to the PATH
  2. run the script as . scriptname

The . (dot) will make sure the script is not run in a child shell.

两相知 2024-07-28 07:07:14

可以起一个别名

alias your_cmd=". your_cmd"

把上面的放在一起,如果不想写开头的“.”, 。 每一次
你想将你的脚本源到 shell 环境,
或者如果您只是不想记住必须这样做
以使脚本正常工作。

Putting the above together, you can make an alias

alias your_cmd=". your_cmd"

if you don't want to write the leading "." each time
you want to source your script to the shell environment,
or if you simply don't want to remember that must be done
for the script to work correctly.

他是夢罘是命 2024-07-28 07:07:14

如果您使用的是 bash,您可以尝试

在 .bashrc 文件中添加别名:添加此行:

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

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

If you are using bash you can try alias:

into the .bashrc file add this line:

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

when you write "p" on the command line, it will change the directory.

天冷不及心凉 2024-07-28 07:07:14

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

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

#!/bin/bash
cd $1
exec bash

这样您将位于 /home/test 中,直到退出( exit 或 Ctrl+C )此 shell。

If you run a bash script then it will operates on its current environment or on those of its children, never on the parent.

If goal is to run your command :
goto.sh /home/test
Then work interactively in /home/test one way is to run a bash interactive subshell within your script :

#!/bin/bash
cd $1
exec bash

This way you will be in /home/test until you exit ( exit or Ctrl+C ) of this shell.

爱她像谁 2024-07-28 07:07:14

使用pushd将当前目录推送到目录堆栈上并将其更改为给定目录,popd将目录置于堆栈顶部并更改为该目录。

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

With pushd the current directory is pushed on the directory stack and it is changed to the given directory, popd get the directory on top of the stack and changes then to it.

pushd ../new/dir > /dev/null
# do something in ../new/dir
popd > /dev/null
农村范ル 2024-07-28 07:07:14

在 shell 脚本中添加以下 cd 行:

exec $SHELL

Add below cd line in your shellscript this:

exec $SHELL
薆情海 2024-07-28 07:07:14

只需转到

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

Simply go to

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

and add this code next to the last line:

alias yourcommand="cd /the_path_you_wish"

Then quit editor.

Then type:

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

now you can use: yourcommand in terminal

毁虫ゝ 2024-07-28 07:07:14

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

I've made a script to change directory. take a look: https://github.com/ygpark/dj

眼眸里的那抹悲凉 2024-07-28 07:07:14

基本上我们使用 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 

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

Basically we use cd.. to come back from every directory. I thought to make it more easy by giving the number of directories with which you need to come back at a time. You can implement this using a separate script file using the alias command . For example:

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'   

After using source code.sh in the current shell you can use :

$back 2 

to come two steps back from the current directory. Explained in detail over here. It is also explained over there how to put the code in ~/.bashrc so that every new shell opened will automatically have this new alias command. You can add new command to go to specific directories by modifying the code by adding more if conditions and different arguments. You can also pull the code from git over here.

终止放荡 2024-07-28 07:07:14

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

#!/bin/bash

cd folder1/folder2/

现在运行脚本,前面带有 .
. 使用当前线程/会话来执行脚本。

. shellfile.sh

This is a simplified compilation of above answer.
Create a shell file shellfile.sh
In the script change your directory inside a function

#!/bin/bash

cd folder1/folder2/

Now run the script with . before it.
. uses the current thread/session to execute the script.

. shellfile.sh
苏别ゝ 2024-07-28 07:07:14

这是我目前对 bash 的做法(在 Debian 上测试过)。 也许有更好的方法:

不要使用 exec bash 来执行此操作,例如如下所示:

#!/bin/bash
cd $1
exec bash

因为虽然它看起来有效,但之后
你运行它并且你的脚本完成,是的,你会在正确的位置
目录,但您将位于子 shell 中,您可以通过以下方式确认
之后按 Ctrl+D,您将看到它退出子 shell,
将您带回原始目录。

这通常不是您希望脚本用户在之后保持的状态
他们运行的脚本返回,因为它们所在的位置并不明显
一个子 shell,现在他们基本上有两个打开的 shell
以为他们只有一个。 他们可能会继续使用这个子 shell 而没有意识到这一点,这可能会产生意想不到的后果。

如果您确实希望脚本退出并在
新目录,最好更改 PS1 变量,以便
脚本用户有一个视觉指示器,表明他们仍然有一个子 shell
打开。

这是我想出的一个例子。 这是两个文件,一个是你直接调用的outer.sh,
和一个inner.sh,它源自outer.sh 脚本。 外层
script 设置两个变量,然后获取内部脚本,以及
之后它回显两个变量(第二个变量刚刚被
由内部脚本修改)。 然后它会制作一个临时副本
当前用户的 ~/.bashrc 文件,添加 PS1 变量的覆盖
其中,还有一个清理例程,最后它运行 exec bash
--rcfile 指向 .bashrc.tmp 文件,用修改后的环境初始化 bash,包括修改后的提示符和清理
例行公事。

outer.sh 退出后,您将留在所需目录的子 shell 中(在本例中为 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$

如果您按 Ctrl-D 退出子 shell,它应该通过删除来清理
testdir/ 目录中的临时 .bashrc.tmp 文件

我想知道是否有比复制 .bashrc 文件更好的方法
像这样在子 shell 中正确更改 PS1 var...

This is my current way of doing it for bash (tested on Debian). Maybe there's a better way:

Don't do it with exec bash, for example like this:

#!/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:

file 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

file 2: inner.sh

cd testdir
var2="bird"

then run:

$ mkdir testdir
$ chmod 755 outer.sh

$ ./outer.sh

it should output:

hello
bird

and then drop you into your subshell using exec bash, but with a
modified prompt which makes that obvious, something like:

(subshell) user@computername:~/testdir$

and if you Ctrl-D out of the subshell, it should clean up by deleting
a temporary .bashrc.tmp file in the testdir/ directory

I wonder if there's a better way than having to copy the .bashrc file
like that though to change the PS1 var properly in the subshell...

云柯 2024-07-28 07:07:14

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

假设在您是管理员的个人 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. 源mongobin
  4. pwd

瞧!

This approach is easier for me.

Suppose on a personal iMac where you are an admin, under the default directory when a command window is opened, /Users/jdoe, this will be the directory to go to: /Users/jdoe/Desktop/Mongo/db.3.2.1/bin.

These are the steps that can have the job done:

  1. vi mongobin, in which I entered:
    cd /Users/jdoe/Desktop/Mongo/db.3.2.1/bin as the first line.
  2. chmod 755 mongobin
  3. source mongobin
  4. pwd

Voila!

清晨说晚安 2024-07-28 07:07:14

我还创建了一个名为 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

I've also created a utility called goat that you can use for easier navigation.

You can view the source code on GitHub.

As of v2.3.1 the usage overview looks like this:

# 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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文