首页 文章

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

提问于
浏览
641

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

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

我将此文件保存为proj,使用 chmod 添加了执行权限,并将其复制到 /usr/bin . 当我通过以下方式调用它时: proj ,它什么也没做 . 我究竟做错了什么?

29 回答

  • 1

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

    . script_name
    

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

    source script_name
    

    这避免了子shell,并允许任何变量或内置函数(包括 cd )来影响当前的shell .

  • 131

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

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

    重启终端,您可以输入

    move_me
    

    然后您将被移动到目标文件夹 .

  • 11

    只需运行:

    cd /home/xxx/yyy && command_you_want
    
  • 5

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

    它包含一些hackish答案,例如https://stackoverflow.com/a/2375174/755804(通过gdb更改父进程目录,不要这样做)和https://stackoverflow.com/a/51985735/755804(命令 tailcd 将cd dirname注入父进程的输入流;好吧,理想情况下它应该是bash的一部分而不是hack)

  • 0

    您可以结合使用Adam&Greg的别名和点式方法来制作更具动感的内容 -

    alias project=". project"
    

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

  • 0

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

    #!/bin/bash
    
    # saved as mov_dir.sh
    cd ~/mt/v3/rt_linux-rt-tools/
    bash
    

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

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

    这将甚至会在您退出时返回原始目录(CTRL d)

  • 201

    在寻找您想要运行的脚本是一种解决方案时,您应该知道此脚本可以直接修改当前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目录书签 .

  • 3

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

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

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

    您可以在其中输入或将其放入各种shell启动文件中 .

  • 36

    您可以使用运算符&&:

    cd myDirectory && ls

  • 25

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

    alias p='. p'
    

    在你的.bashrc中

  • 3

    制作一个将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,你就在那里 .

  • 18

    Using Bash Profile Functions :

    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 快速编辑/创建这些文件

    Script Example

    cdd 制作 cd .. 的快捷方式

    cdd() {
      cd ..
    }
    

    是捷径

    ll() {
      ls -l -h
    }
    

    是捷径

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

    Howto :

    复制文件末尾的函数并重新启动终端,然后运行 cdd 或您编写的任何函数

  • 3

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

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

    . proj
    

    但我更喜欢Greg建议在这个简单的例子中使用别名 .

  • -1

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

    您可能想要使用symbolic link . 它允许您为文件或目录创建"shortcut",因此您只需输入类似 cd my-project 的内容 .

  • 431

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

    shopt -s cdable_vars
    

    在你的 ~/.bashrc 允许 cd 到环境变量的内容 .

    创建这样的环境变量:

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

    你可以使用:

    cd myjava
    

    Other alternatives .

  • 90

    您可以组合别名和脚本,

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

    只要脚本回显目标路径 . 请注意,这些是围绕脚本名称的反引号 .

    例如,您的脚本可能是

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

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

  • 0

    最后使用exec bash

    一个bash脚本对它进行操作当前环境或其子环境,但从不在其父环境中 .

    但是,这个问题经常被问到,因为在从另一个目录执行bash脚本之后,想要在某个目录中保留bash提示符 .

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

    #!/bin/bash
    cd /home/tree/projects/java
    exec bash
    
  • 7

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

    创建一个名为case的文件

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

    #!/bin/sh
    
    cd /home/"$1"
    

    保存然后:

    chmod +x case
    

    我还在 .bashrc 中创建了一个别名:

    alias disk='cd /home/; . case'
    

    现在当我输入:

    case 12345
    

    基本上我打字:

    cd /home/12345
    

    你可以在'case'之后输入任何文件夹:

    case 12
    
    case 15
    
    case 17
    

    这就像打字:

    cd /home/12
    
    cd /home/15
    
    cd /home/17
    

    分别

    在我的情况下,路径更长 - 这些家伙早先用~info总结了它 .

  • 2

    如果以反斜杠结束行,则可以在同一子shell中执行某些行 .

    cd somedir; \
    pwd
    
  • 3

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

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

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

    cd 在脚本's shell. When the script ends, that shell exits, and then you are left in the directory you were. 167294 the script, don'中运行它 . 代替:

    ./myscript.sh
    

    . ./myscript.sh
    

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

  • 5

    我使用 . <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$
    
  • 544

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

    1 -

    $ nano~./ bashrc

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

    2-

    $ source~ / .bashrc

    3 -

    $ switchp java

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

    希望有所帮助!

  • 0

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

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

    cdproj
    

    要么

    cdproj project_name
    

    这是功能定义 .

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

    别忘了找你的 .bash_profile

  • 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文件) .

  • 7

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

  • 9

    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
    
  • 7

    你可以这样做:

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

    编辑:这也可以“点缀”,以防止后续shell的创建 .

    例:

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

相关问题