Why doesn't “cd” work in a shell script?
我正在尝试编写一个小脚本,将当前目录更改为我的项目目录:
1 2 | #!/bin/bash cd /home/tree/projects/java |
我将这个文件保存为proj,添加了
shell脚本在子shell中运行,每个子shell都有自己的当前目录概念。
解决此问题的一种方法是使用别名:
1 | alias proj="cd /home/tree/projects/java" |
你没做错什么!您已经更改了目录,但只在运行脚本的子shell中。
您可以使用"dot"命令在当前进程中运行脚本:
1 | . proj |
但我更喜欢格雷格的建议,在这个简单的例子中使用别名。
脚本中的
解决这个问题的POSIX兼容方法是定义一个shell过程,而不是一个shell调用的命令脚本。
1 2 3 | jhome () { cd /home/tree/projects/java } |
您可以将其键入或放入各种shell启动文件之一。
1 | ./myscript.sh |
做
1 | . ./myscript.sh |
(注意脚本名称前面的点和空格。)
要制作一个bash脚本,该脚本将CD到一个选择目录:
创建脚本文件
1 2 3 4 | #!/bin/sh # file : /scripts/cdjava # cd /home/askgelal/projects/java |
然后在启动文件中创建别名。
1 2 3 4 | #!/bin/sh # file /scripts/mastercode.sh # alias cdjava='. /scripts/cdjava' |
- 我创建了一个启动文件,在其中转储所有别名和自定义函数。
- 然后我将这个文件源到我的.bashrc中,以便在每次启动时设置它。
例如,创建主别名/函数文件:/scripts/mastercode.sh(将别名放在此文件中。)
然后在.bashrc文件的末尾:
1 | source /scripts/mastercode.sh |
现在它很容易CD到你的Java目录,只需键入CDJava,你就在那里。
杰里米·鲁滕使用符号链接的想法引发了一种想法,这种想法并没有越过任何其他答案。用途:
1 | CDPATH=:$HOME/projects |
前导冒号很重要;这意味着如果当前目录中有目录"dir",那么"EDOCX1"(4)将更改为该目录,而不是跳到其他地方。如图所示设置值后,可以执行以下操作:
1 | cd java |
而且,如果在当前目录中没有Java目录,那么它将直接带到$home /jpjs/java-没有别名,没有脚本,没有可疑的执行器或点命令。
我的$home是/users/jleverer;我的$cdpath是:
1 | :/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 |
您可以使用
1 | . script_name |
或者,它更易读但外壳特定的别名
1 | source script_name |
这避免了子shell,并允许任何变量或内置(包括
我通过使用OCX1(2)获得了我的代码
这是我的节目单
1 2 3 | #!/bin/bash echo"Taking you to eclipse's workspace." cd /Developer/Java/workspace |
这是我的终点站
1 2 3 4 | nova:~ Kael$ nova:~ Kael$ . workspace.sh Taking you to eclipe's workspace. nova:workspace Kael$ |
最后使用
A bash script operates on its current environment or on that of its
children, but never on its parent environment.
然而,这个问题经常会被问到,因为在从另一个目录执行bash脚本之后,您希望留在某个目录中的bash提示符下。
如果是这种情况,只需在脚本末尾执行子bash实例:
1 2 3 | #!/usr/bin/env bash cd /home/tree/projects/java exec bash |
简单运行:
1 | cd /home/xxx/yyy && command_you_want |
当您启动shell脚本时,它会运行该shell的一个新实例(
您可以执行以下操作:
1 2 3 4 | #!/bin/bash cd /your/project/directory # start another shell and replacing the current exec /bin/bash |
编辑:这也可以是"点式的",以防止创建后续的shell。
例子:
1 | . ./previous_script (with or without the first line) |
在我的特殊情况下,我需要多次更改同一目录。所以在我的.bashrc(我使用Ubuntu)中,我添加了
1
$ nano ~./bashrc
1 2 3 4 | function switchp { cd /home/tree/projects/$1 } |
2
$ source ~/.bashrc
3
$ switchp java
直接实现:CD/home/树/项目/ Java
希望有帮助!
您可以组合别名和脚本,
1 | alias proj="cd \`/usr/bin/proj !*\`" |
前提是该脚本响应目标路径。请注意,这些是围绕脚本名称的背景。
例如,您的脚本可以是
1 2 | #!/bin/bash echo /home/askgelal/projects/java/$1 |
这种技术的优势在于,脚本可以接受任意数量的命令行参数,并通过可能复杂的逻辑计算出不同的目标。
它只更改脚本本身的目录,而当前目录保持不变。
您可能希望改用符号链接。它允许您对一个文件或目录进行"快捷方式",因此您只需要键入类似于
为了快速浏览目录,有$cdpath、cdargs和自动生成别名的方法
http://jackndempsey.blogspot.com/2008/07/cdargs.html
网址:http://muness.blogspot.com/2008/06/lazy-bash-cd-aliaes.html
https://web.archive.org/web/1/http://articles.technrepublic%2ecom%2ecom/5100-10878_11-5827311.html
您可以将Adam&Greg的别名和点方法结合起来,使之更具动态性。-
1 | alias project=". project" |
现在运行项目别名将在当前shell中执行项目脚本,而不是子shell。
在~/.bash_配置文件中。添加下一个函数
1 2 3 | move_me() { cd ~/path/to/dest } |
重新启动终端,您可以键入
1 | move_me |
您将被移动到目标文件夹。
您可以使用运算符&;&;:
CD我的目录
这应该是你想要的。更改到感兴趣的目录(从脚本中),然后生成一个新的bash shell。
1 2 3 4 5 | #!/bin/bash # saved as mov_dir.sh cd ~/mt/v3/rt_linux-rt-tools/ bash |
如果您运行这个,它将把您带到感兴趣的目录,当您退出它时,它将把您带回到原始位置。
1 2 3 4 | root@intel-corei7-64:~# ./mov_dir.sh root@intel-corei7-64:~/mt/v3/rt_linux-rt-tools# exit root@intel-corei7-64:~# |
当您退出时,这甚至会使您返回到原始目录(ctrl+d)
虽然寻源您要运行的脚本是一种解决方案,但您应该知道,然后该脚本可以直接修改当前shell的环境。而且,不可能再传递参数了。
另一种方法是在bash中实现脚本作为函数。
1 2 3 4 | function cdbm() { cd whereever_you_want_to_go echo"Arguments to the functions were $1, $2, ..." } |
自动跳转使用此技术:http://github.com/joelthelion/autojump/wiki,为您提供学习shell目录书签。
很长一段时间之后,但我做了以下事情:
创建一个名为case的文件
将以下内容粘贴到文件中:
1 2 3 | #!/bin/sh cd /home/"$1" |
保存它,然后:
1 | chmod +x case |
我还在我的
1 | alias disk='cd /home/; . case' |
现在,当我键入:
1 | case 12345 |
基本上我在打字:
1 | cd /home/12345 |
您可以在"case"后键入任何文件夹:
1 2 3 4 5 | case 12 case 15 case 17 |
就像打字:
1 2 3 4 5 | cd /home/12 cd /home/15 cd /home/17 |
分别地
在我的例子中,路径要长得多——这些人用前面的信息总结了这一点。
你可以在你的
以下函数接受项目的可选参数。例如,您可以运行
1 | cdproj |
或
1 | cdproj project_name |
这是函数定义。
1 2 3 4 5 6 7 8 | cdproj(){ dir=/Users/yourname/projects if ["$1" ]; then cd"${dir}/${1}" else cd"${dir}" fi } |
别忘了找到你的
我有一个名为p的简单bash脚本来管理目录更改ongithub.com/godzilla/bash-stuff只需将脚本放在本地bin目录中(/usr/local/bin)放
1 | alias p='. p' |
在你的BASHC中
请注意讨论如何设置父进程的工作目录?
它包含一些黑客的答案,例如https://stackoverflow.com/a/2375174/755804(通过gdb更改父进程目录,不要这样做)和https://stackoverflow.com/a/51985735/755804(命令
如果您使用fish作为外壳,最好的解决方案是创建一个函数。例如,对于原始问题,可以复制下面的4行并将它们粘贴到fish命令行中:
1 2 3 4 | function proj cd /home/tree/projects/java end funcsave proj |
这将创建该函数并将其保存以供以后使用。如果项目发生更改,只需使用新路径重复该过程。
如果愿意,可以通过执行以下操作手动添加函数文件:
1 | nano ~/.config/fish/functions/proj.fish |
并输入文本:
1 2 3 | function proj cd /home/tree/projects/java end |
最后按ctrl+x退出,然后按y返回保存更改。
(注意:使用funcsave的第一个方法为您创建proj.fish文件)。
您不需要脚本,只需设置正确的选项并创建一个环境变量。
1 | shopt -s cdable_vars |
在您的
创建这样的环境变量:
1 | export myjava="/home/tree/projects/java" |
你可以使用:
1 | cd myjava |
其他替代方案。
使用bash profile函数:
bash概要文件的一个特性是存储可以在终端或bash脚本中运行的自定义函数,就像运行应用程序/命令一样,这也可以用作长命令的快捷方式。
为了使您的功能更加高效,您需要在多个文件的末尾复制您的功能。
1 2 3 4 | /home/user/.bashrc /home/user/.bash_profile /root/.bashrc /root/.bash_profile |
您可以使用ecx1〔5〕快速编辑/创建这些文件
脚本示例
用
1 2 3 | cdd() { cd .. } |
LS快捷方式
1 2 3 | ll() { ls -l -h } |
LS快捷方式
1 2 3 | lll() { ls -l -h -a } |
Howto:
在文件末尾复制您的函数并重新启动终端,然后您可以运行
如果行以反斜杠结尾,则可以在同一子shell中执行一些行。
1 2 | cd somedir; \ pwd |