为什么“cd”不能在shell脚本中工作?

时间:2008-11-01 02:07:09

标签: linux shell

我正在尝试编写一个小脚本来将当前目录更改为我的项目目录:

#!/bin/bash
cd /home/tree/projects/java

我将此文件保存为proj,添加了chmod的执行权限,并将其复制到/usr/bin。我打电话给: proj,它什么也没做。我做错了什么?

32 个答案:

答案 0 :(得分:581)

Shell脚本在子shell中运行,每个子shell都有自己的当前目录概念。 cd成功,但是一旦子shell退出,你就会回到交互式shell中,并且没有任何改变。

解决此问题的一种方法是使用别名:

alias proj="cd /home/tree/projects/java"

答案 1 :(得分:457)

你没有做错任何事!您已经更改了目录,但仅在运行脚本的子shell中。

您可以使用“dot”命令在当前进程中运行脚本:

. proj

但我更喜欢Greg建议在这个简单的情况下使用别名。

答案 2 :(得分:208)

脚本中的cd技术上工作,因为它更改了运行脚本的shell的目录,但这是一个从交互式shell派生的独立进程。

解决此问题的Posix兼容方法是定义 shell过程而不是shell调用的命令脚本

jhome () {
  cd /home/tree/projects/java
}

您只需输入或将其放入各种shell启动文件中即可。

答案 3 :(得分:140)

cd在脚本的shell中完成。当脚本结束时,该shell退出,然后您将保留在您所在的目录中。 “源”脚本,不要运行它。而不是:

./myscript.sh

DO

. ./myscript.sh

(注意脚本名称前的点和空格。)

答案 4 :(得分:90)

创建一个将cd到选择目录的bash脚本:

创建脚本文件

#!/bin/sh
# file : /scripts/cdjava
#
cd /home/askgelal/projects/java

然后在启动文件中创建一个别名。

#!/bin/sh
# file /scripts/mastercode.sh
#
alias cdjava='. /scripts/cdjava'

  • 我创建了一个启动文件,我将转储所有别名和自定义函数。
  • 然后我将此文件发送到我的.bashrc中,以便在每次启动时设置它。

例如,创建主别名/函数文件: /scripts/mastercode.sh
(将别名放在此文件中。)

然后在 .bashrc 文件的末尾:

source /scripts/mastercode.sh



现在很容易cd到你的java目录,只需输入cdjava就可以了。

答案 5 :(得分:36)

杰里米·鲁腾(Jeremy Ruten)使用符号链接的想法引发了一个没有超越任何其他答案的想法。使用:

CDPATH=:$HOME/projects

前导结肠很重要;这意味着如果当前目录中有一个目录'dir',那么'cd dir'将更改为该目录,而不是在其他地方跳转。如图所示设置值,您可以执行以下操作:

cd java

并且,如果当前目录中没有名为java的子目录,那么它将直接转到$ HOME / projects / java - 没有别名,没有脚本,没有可疑的exec或点命令。

我的$ HOME是/ Users / jleffler;我的$ CDPATH是:

:/Users/jleffler:/Users/jleffler/mail:/Users/jleffler/src:/Users/jleffler/src/perl:/Users/jleffler/src/sqltools:/Users/jleffler/lib:/Users/jleffler/doc:/Users/jleffler/work

答案 6 :(得分:36)

您可以使用.在当前shell环境中执行脚本:

. script_name

或者更具可读性但是特定于shell的别名source

source script_name

这避免了子shell,并允许任何变量或内置函数(包括cd)代替当前的shell。

答案 7 :(得分:25)

我使用. <your file name>

让我的代码工作

./<your file name>无效,因为它不会更改终端中的目录,只会更改特定于该脚本的目录。

这是我的程序

#!/bin/bash 
echo "Taking you to eclipse's workspace."
cd /Developer/Java/workspace

这是我的终端

nova:~ Kael$ 
nova:~ Kael$ . workspace.sh
Taking you to eclipe's workspace.
nova:workspace Kael$ 

答案 8 :(得分:21)

最后使用exec bash

  

bash脚本在其当前环境或其当前环境上运行   孩子,但从不在父母的环境中。

但是,这个问题经常被问到,因为在执行 bash脚本之后,有人希望留在某个目录中的(新)bash提示符。

如果是这种情况,只需在脚本末尾执行子bash实例

#!/usr/bin/env bash
cd /home/tree/projects/java
exec bash

答案 9 :(得分:17)

只需运行:

{{1}}

答案 10 :(得分:12)

当您触发shell脚本时,它会运行该shell的{em> new 实例(/bin/bash)。因此,您的脚本只会启动一个shell,更改目录并退出。换句话说,shell脚本中的cd(以及其他此类命令)不会影响也无法访问启动它们的shell。

答案 11 :(得分:9)

您可以执行以下操作:

#!/bin/bash
cd /your/project/directory
# start another shell and replacing the current
exec /bin/bash

编辑:这也可以“点缀”,以防止后续炮弹的创建。

示例:

. ./previous_script  (with or without the first line)

答案 12 :(得分:9)

在我的特定情况下,我需要多次更改同一目录。 所以在我的.bashrc(我用ubuntu)上我添加了

1 -

  

$ nano~./ bashrc

 function switchp
 {
    cd /home/tree/projects/$1
 }

2-

  

$ source~ / .bashrc

3 -

  

$ switchp java

直接它会:cd / home / tree / projects / java

希望有所帮助!

答案 13 :(得分:7)

您可以合并别名和脚本

alias proj="cd \`/usr/bin/proj !*\`"

前提是脚本回显目标路径。请注意,这些是围绕脚本名称的反引号。

例如,您的脚本可能是

#!/bin/bash
echo /home/askgelal/projects/java/$1

这种技术的优点是脚本可以接受任意数量的命令行参数,并发出可能由复杂逻辑计算的不同目的地。

答案 14 :(得分:7)

它只更改脚本本身的目录,而当前目录保持不变。

您可能希望使用symbolic link代替。它允许您创建文件或目录的“快捷方式”,因此您只需键入类似cd my-project的内容。

答案 15 :(得分:5)

答案 16 :(得分:5)

你可以结合亚当&amp;格雷格的别名和点方法可以创造出更具活力的东西 -

alias project=". project"

现在运行项目别名将在当前shell中执行项目脚本而不是子shell。

答案 17 :(得分:3)

在寻找您想要运行的脚本是一种解决方案时,您应该知道此脚本可以直接修改当前shell的环境。此外,再也无法传递参数。

另一种方法是在bash中将脚本实现为函数。

function cdbm() {
  cd whereever_you_want_to_go
  echo "Arguments to the functions were $1, $2, ..."
}

autojump:http://github.com/joelthelion/autojump/wiki使用此技术为您提供学习shell目录书签。

答案 18 :(得分:3)

您可以使用运营商&amp;&amp; :

cd myDirectory&amp;&amp; LS

答案 19 :(得分:3)

这应该做你想要的。切换到感兴趣的目录(从脚本中),然后生成一个新的bash shell。

root@intel-corei7-64:~# ./mov_dir.sh

root@intel-corei7-64:~/mt/v3/rt_linux-rt-tools# exit
root@intel-corei7-64:~#

如果你运行它,它将带你到感兴趣的目录,当你退出它时,它会带你回到原来的位置。

public class InventoryItem extends AsyncTask<Void,Void,Void>{
        String imageURL = "";
        String itemName = "";
        String itemDesc = "";
        String itemRarity = "";
        String itemType = "";
        JSONObject itemJson = null;

        InventoryItem(JSONObject json){
            itemJson = json;
            Log.d("StringSubclass","Inventory Item");
        }

        @Override
        protected Void doInBackground(Void... voids) {
            Log.d("StringSubclass","doInBG Inventory Item");
            try {
                imageURL = "http://www.bungie.net"+itemJson.getJSONObject("Response").getJSONObject("data").getJSONObject("inventoryItem").getString("icon");
                Log.d("StringSubclass",imageURL);
                itemName = itemJson.getJSONObject("Response").getJSONObject("data").getJSONObject("inventoryItem").getString("itemName");
                itemDesc = itemJson.getJSONObject("Response").getJSONObject("data").getJSONObject("inventoryItem").getString("itemDescription");
                itemRarity = itemJson.getJSONObject("Response").getJSONObject("data").getJSONObject("inventoryItem").getString("tierTypeName");
                itemType = itemJson.getJSONObject("Response").getJSONObject("data").getJSONObject("inventoryItem").getString("itemTypeName");

            } catch (JSONException e) {
                e.printStackTrace();
            }


            return null;
        }


        public String getItemType() {
            return itemType;
        }

        public String getItemRarity() {
            return itemRarity;
        }

        public String getItemDesc() {
            return itemDesc;
        }

        public String getItemName() {
            return itemName;
        }

        public String getImageURL() {
            return imageURL;
        }
    }

当你退出时,这甚至会让你回到原来的目录( CTRL + d

答案 20 :(得分:3)

在〜/ .bash_profile文件中。添加下一个功能

move_me() {
    cd ~/path/to/dest
}

重新启动终端,您可以输入

move_me 

您将被移至目标文件夹。

答案 21 :(得分:2)

您可以在.bash_profile中创建如下所示的功能,它可以顺利运行。

以下函数采用可选参数,即项目。 例如,您可以运行

cdproj

cdproj project_name

这是功能定义。

cdproj(){
    dir=/Users/yourname/projects
    if [ "$1" ]; then
      cd "${dir}/${1}"
    else
      cd "${dir}"
    fi
}

请勿忘记提供.bash_profile

答案 22 :(得分:2)

LOOOOOng之后的时间,但我做了以下事情:

创建一个名为case

的文件

将以下内容粘贴到文件中:

#!/bin/sh

cd /home/"$1"

保存,然后:

chmod +x case

我还在.bashrc

中创建了一个别名
alias disk='cd /home/; . case'

现在当我输入:

case 12345

基本上我正在打字:

cd /home/12345

您可以在“案例”之后键入任何文件夹:

case 12

case 15

case 17

就像打字:

cd /home/12

cd /home/15

cd /home/17
分别

在我的情况下,路径要长得多 - 这些人早先用~info总结了它。

答案 23 :(得分:0)

我有一个名为p的简单bash脚本,用于管理目录更改为github.com/godzilla/bash-stuff
只需将脚本放在本地bin目录(/ usr / local / bin)中即可 并放上

alias p='. p'
你的.bashrc中的

答案 24 :(得分:0)

您不需要脚本,只需设置正确的选项并创建环境变量。

shopt -s cdable_vars
您的~/.bashrc中的

允许cd获取环境变量的内容。

创建这样的环境变量:

export myjava="/home/tree/projects/java"

你可以使用:

cd myjava

Other alternatives

答案 25 :(得分:0)

如果您使用fish作为shell,最佳解决方案是创建一个函数。例如,根据原始问题,您可以复制下面的4行并将它们粘贴到您的fish命令行中:

function proj
   cd /home/tree/projects/java
end
funcsave proj

这将创建该功能并保存以供日后使用。如果您的项目发生变化,只需使用新路径重复该过程。

如果您愿意,可以通过执行以下操作手动添加功能文件:

nano ~/.config/fish/functions/proj.fish

并输入文字:

function proj
   cd /home/tree/projects/java
end

最后按ctrl + x退出,然后按y返回以保存更改。

注意:第一种使用funcsave的方法为你创建了proj.fish文件。)

答案 26 :(得分:0)

使用Bash配置文件功能

bash配置文件的一个特性是存储可以在终端或bash脚本中运行的自定义函数,就像运行应用程序/命令一样,这也可以用作长命令的快捷方式。

为了使您的功能高效系统,您需要在几个文件的末尾复制您的功能

/home/user/.bashrc
/home/user/.bash_profile
/root/.bashrc
/root/.bash_profile

您可以sudo kwrite /home/user/.bashrc /home/user/.bash_profile /root/.bashrc /root/.bash_profile快速编辑/创建这些文件

脚本示例

使用cd ..

制作cdd的快捷方式
cdd() {
  cd ..
}

是快捷方式

ll() {
  ls -l -h
}

是快捷方式

lll() {
  ls -l -h -a
}

如何:

在文件末尾复制你的功能并重新启动你的终端然后你可以运行cdd或你写的任何功能

答案 27 :(得分:0)

请注意讨论How do I set the working directory of the parent process?

它包含一些骇人听闻的答案,例如 https://stackoverflow.com/a/2375174/755804(通过gdb更改父进程目录,请勿执行此操作)和https://stackoverflow.com/a/51985735/755804(将{em> cd dirname 注入到其中的命令tailcd)父进程;嗯,理想情况下,它应该是bash的一部分,而不是hack)

答案 28 :(得分:0)

这是一个古老的问题,但我真的很惊讶,我在这里没有看到这个窍门

您可以使用

来代替使用 cd
export PWD=the/path/you/want

无需创建子外壳或使用别名。

请注意,您有责任确保/ path / you / want存在。

答案 29 :(得分:0)

我必须在tcsh中工作,我知道这不是一个很好的解决方案,但是例如,如果我必须将文件夹更改为一个单词不同的路径,则可以使用别名完成整个操作

interface DataSet {
  position: number;
  name: string;
  weight: string;
  symbol: string;
  config?: Partial<Record<Exclude<keyof this, "config">, CellConfig>>;
}

如果路径总是固定的,则正义

a alias_name 'set a = `pwd`; set b = `echo $a | replace "Trees" "Tests"` ; cd $b'

应该工作 在上面的行中,设置了新的文件夹路径

答案 30 :(得分:0)

这将answer by Sergeunrelated answer by David组合在一起。它会更改目录,然后启动用户的默认shell ,而不是强制使用bash shell。但是,它需要getent/etc/passwd才能检测默认的外壳程序。

#!/usr/bin/env bash
cd desired/directory
USER_SHELL=$(getent passwd <USER> | cut -d : -f 7)
$USER_SHELL

当然,这仍然与创建嵌套shell相同。

答案 31 :(得分:-1)

如果使用反斜杠结束行,则可以在同一个子shell中执行一些行。

cd somedir; \
pwd