从Bash脚本更改当前目录


190

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

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

#!/bin/bash
cd /home/artemb

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


2
只是一个增强建议:如果您使用pushd(可能重定向到>/dev/null以抑制其输出)而不是cd,则可以稍后使用来返回上一个目录popd
mklement0 2012年

Answers:


173

您需要将脚本转换为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
}

原因是每个进程都有自己的当前目录,并且当您从外壳执行程序时,该程序将在新进程中运行。标准的“ cd”,“ pushd”和“ popd”内置于shell解释器中,因此它们会影响shell进程。

通过使程序成为Shell函数,您将添加自己的进程内命令,然后任何目录更改都会反映在Shell进程中。


2
您将如何在tcsh中执行此操作?
joedborg 2011年

4
+1。我注意到的一件事是在文件中,我们必须在调用它之前定义函数。它可以帮助像我这样没有经验的人。
虎山

定义函数和创建别名之间的最大区别是什么?
HelloGoodbye 2015年

1
创建此myprog.sh文件并将其添加到.bashrc后,如何运行脚本?我应该从另一个Shell文件中调用函数还是直接从Shell中调用函数?看来这两种方法都行不通……
Andrea Silvestri

1
@AndreaSilvestri退出并重新登录,或获取.bashrc。在运行.bashrc之前,将其添加到.bashrc不会执行任何操作。
乔恩·斯特雷尔

212

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

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

. myscript.sh

.会在目前的环境评估脚本,所以它可能被改变


4
+1是因为您是对的。尽管我由衷的怀疑,他每次需要时都想提供一个目录更改脚本的源代码。而且,.sh扩展完全不正确。不要使用它们。
2009年

1
是的,通常最好不要那样使用。大多数时候,您很高兴当前的环境不会受到影响。但是然后我有了脚本来为我执行一些设置任务,包括更改到正确的位置,然后再执行。他们也是。顺便说一句。.sh当然是个人风格的问题。我可能不会在系统范围内安装脚本时使用它。但是在我的〜/ bin中,我用它们知道什么是:)
诺伯特·哈特尔

10
@lhunath为什么.sh扩展名完全不正确?
卡尔·普里切特


1
对我而言,那篇文章的推理是虚假的。似乎已经预先知道了结果,但是找到原因并不是那么容易。所以我的立场是个人风格,没有别的。
诺伯特·哈特

55

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

  1. 将该脚本添加到 PATH
  2. 运行脚本为 . scriptname

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


38

综上所述,您可以创建一个别名

alias your_cmd=". your_cmd"

如果您不想写开头的“。” 每当您想将脚本来源提供给Shell环境时,或者您只是不想记住脚本必须正确执行才能正常工作。


重启后,这种情况会持续存在吗?
SDsolar '17

1
@SDsolar您需要将此文件添加到〜/ .bashrc文件中以使其持久。对我来说就像一个魅力。
拉斐尔G.17年

可以放在〜/ .bash_aliases中
Champ

~/.bash_aliasesBash启动时,@ Champ 并非总是来源。
Mateusz Piotrowski

31

如果您正在使用bash,则可以尝试使用别名:

到.bashrc文件中,添加以下行:

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

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


1
+1作为别名。shell功能很有趣,但是OP要求使用cd进行简单的导航。我猜想大多数人都需要这样的脚本来导航源代码分支,并且该别名就足够了
Brad Dre

19

如果您运行bash脚本,则它将在其当前环境或其子环境上运行,而不会在父环境上运行。

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

#!/bin/bash
cd $1
exec bash

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


我以为这可以解决我正在运行的Shell脚本的问题,但是相反,它启动了Shell,却忘记了我想要的东西。
vwvan 2014年

13

随着PUSHD当前目录被压入目录栈并将其更改为指定目录,POPD得到栈顶的目录,然后改变它。

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

2
这回答了我的问题—使用S3初始化脚本积极部署此解决方案,并且效果很好。谢谢@seb。
2014年

5

只需转到

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 in terminal



3

基本上,我们cd..习惯从每个目录返回。我想通过给出一次需要返回的目录数来简化操作。您可以使用alias命令使用单独的脚本文件来实现此目的。例如:

代码

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

source code.sh当前shell中使用后,您可以使用:

$back 2 

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


好的解决方案,所以您永远不会弄乱bash的个人资料:)
J4cK

0

这种方法对我来说比较容易。

假设在您是管理员的个人iMac上,打开命令窗口时在默认目录下/ Users / jdoe,该目录将位于以下目录:/Users/jdoe/Desktop/Mongo/db.3.2.1。 / bin。

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

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

瞧!


0

我还创建了一个名为山羊的实用程序,可用于简化导航。

您可以在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

0

我喜欢为不同的项目做同样的事情而无需启动新的shell。

在您的情况下:

cd /home/artemb

将the_script另存为:

echo cd /home/artemb

然后用以下方法启动它:

\`./the_script\`

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



0

声明您的路径:

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

0

只需写入PWD脚本并将其导出到脚本中,更改将继续存在。

export PWD=/your/desired/directory
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.