我正在尝试编写一个小脚本来将当前目录更改为我的项目目录:
#!/bin/bash
cd /home/tree/projects/java
我将此文件保存为 proj,使用 chmod
添加执行权限,并将其复制到 /usr/bin
。当我通过 proj
调用它时,它什么也不做。我究竟做错了什么?
pwd
对其进行测试。因此,在脚本完成之前,您可以检查它是否有效..
cd
命令在脚本中运行良好,请自行尝试。
Shell 脚本在子shell 中运行,每个子shell 都有自己的当前目录概念。 cd
成功,但一旦子 shell 退出,您就会回到交互式 shell,那里没有任何变化。
解决此问题的一种方法是改用别名:
alias proj="cd /home/tree/projects/java"
你没有做错任何事!您已经更改了目录,但仅在运行脚本的子shell 中。
您可以使用“dot”命令在当前进程中运行脚本:
. proj
但我更喜欢 Greg 的建议,在这种简单的情况下使用别名。
.
也拼写为 source
,选择您认为更难忘的那个。
您的脚本中的 cd
在技术上工作,因为它更改了运行脚本的 shell 的目录,但这是一个从交互式 shell 派生的单独进程。
解决这个问题的一种与 Posix 兼容的方法是定义一个 shell 过程,而不是一个 shell 调用的命令脚本。
jhome () {
cd /home/tree/projects/java
}
您可以输入或将其放入各种 shell 启动文件之一。
jhome(){ cd /home/tree/projects/$1; }
cd
在脚本的外壳中完成。当脚本结束时,该 shell 退出,然后您将留在原来的目录中。 “来源”脚本,不要运行它。代替:
./myscript.sh
做
. ./myscript.sh
(注意脚本名称前的点和空格。)
source
相同
myscript.sh
位于 $PATH 中包含的目录中,您可以从任何地方获取它,而无需指定完整路径。
要制作一个将 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 即可。
mastercode.sh
不需要 shabang (#!/bin/sh
),因为它不是(也不能)在子 shell 中执行。但同时,您确实需要记录此文件的外壳“风味”;例如,ksh 或 bash(或 (t)csh/zsh 等),几乎可以肯定它实际上不是 sh
。我通常会添加评论(但不是 shebang)来传达这一点;例如,“此文件旨在获取(来自 bash),而不是作为 shell 脚本运行。”
source
d(通过 alias
)时,这些变量将泄漏到您的 shell 环境中。为避免这种情况,请在函数中完成脚本的所有工作,并在脚本末尾调用它。在函数中,声明任何变量 local
。
您可以使用 .
在当前 shell 环境中执行脚本:
. script_name
或者,它更易读但特定于 shell 的别名 source
:
source script_name
这避免了子 shell,并允许任何变量或内置函数(包括 cd
)改为影响当前 shell。
Jeremy Ruten 使用符号链接的想法引发了一个尚未跨越任何其他答案的想法。利用:
CDPATH=:$HOME/projects
前导冒号很重要;这意味着如果当前目录中有目录“dir”,那么“cd dir
”将更改为该目录,而不是跳到其他地方。使用如图所示设置的值,您可以执行以下操作:
cd java
并且,如果当前目录中没有名为 java 的子目录,那么它将直接将您带到 $HOME/projects/java - 没有别名,没有脚本,没有可疑的执行程序或点命令。
我的 $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
最后使用 exec bash
bash 脚本在其当前环境或其子环境上运行,但从不在其父环境上运行。
但是,这个问题经常被问到,因为在从另一个目录中执行 bash 脚本之后,希望留在某个目录中的(新)bash 提示符处。
如果是这种情况,只需在脚本末尾执行一个子 bash 实例:
#!/usr/bin/env bash
cd /home/tree/projects/java
echo -e '\nHit [Ctrl]+[D] to exit this child shell.'
exec bash
要返回上一个父 bash
实例,请使用 Ctrl+D。
更新
至少对于较新版本的 bash
,最后一行的 exec
不再需要。此外,通过使用 $SHELL
环境变量,可以使脚本与任何首选的 shell 一起工作。然后给出:
#!/usr/bin/env bash
cd desired/directory
echo -e '\nHit [Ctrl]+[D] to exit this child shell.'
$SHELL
exit
时,您将返回到运行此脚本的 shell。
bash
和可能的其他 shell 需要 exec
。我相应地更新了答案。
exec bash
后,我可以留在脚本中并继续运行其他命令吗?
我使用. <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$
. something
和 ./something
有什么区别??这个答案对我有用,我不明白为什么。
. something
允许您从任何位置运行脚本,./something
要求您位于文件所在的目录中。
#!. /bin/bash
?
只需运行:
cd /home/xxx/yyy && command_you_want
当您触发 shell 脚本时,它会运行该 shell (/bin/bash
) 的 new 实例。因此,您的脚本只是启动一个 shell,更改目录并退出。换句话说,shell 脚本中的 cd
(和其他此类命令)不会影响也无法访问启动它们的 shell。
您可以执行以下操作:
#!/bin/bash
cd /your/project/directory
# start another shell and replacing the current
exec /bin/bash
编辑:这也可以“点缀”,以防止创建后续外壳。
例子:
. ./previous_script (with or without the first line)
exit
(或 ctrl+d)退出 shell。别名非常干净(即使 shell 命令输出一个目录,它的输出是 cd - alias something="cd getnewdirectory.sh
")
在我的特殊情况下,我需要为同一个目录更改太多次。所以在我的 .bashrc(我使用 ubuntu)上,我添加了
-
$纳米〜./bashrc
function switchp
{
cd /home/tree/projects/$1
}
2-
$ 源 ~/.bashrc
3 -
$ switchp java
直接它会做: cd /home/tree/projects/java
希望有帮助!
它只会更改脚本本身的目录,而您的当前目录保持不变。
您可能想改用 symbolic link。它允许您为文件或目录创建“快捷方式”,因此您只需键入 cd my-project
之类的内容。
你可以结合 Adam & Greg 的别名和 dot 方法来制作更动态的东西——
alias project=". project"
现在运行项目别名将在当前 shell 中执行项目脚本,而不是子 shell。
您可以结合别名和脚本,
alias proj="cd \`/usr/bin/proj !*\`"
前提是脚本回显目标路径。请注意,这些是围绕脚本名称的反引号。
例如,您的脚本可能是
#!/bin/bash
echo /home/askgelal/projects/java/$1
这种技术的优点是脚本可以采用任意数量的命令行参数并发出由可能复杂的逻辑计算的不同目的地。
proj() { cd "/home/user/projects/java/$1"; }
=> proj "foo"
(或者,proj "foo bar"
<= 如果你有空格)......甚至(例如):proj() { cd "/home/user/projects/java/$1"; shift; for d; do cd "$d"; done; }
=> proj a b c
=>将 cd
放入 /home/user/projects/java/a/b/c
在您的 ~/.bash_profile 文件中。添加下一个功能
move_me() {
cd ~/path/to/dest
}
重启终端,你可以输入
move_me
您将被移动到目标文件夹。
您可以使用运算符 && :
cd myDirectory && ls
&&
,或者仅在它们之间使用 ;
或换行符)但是将其放入脚本中会带您回到“为什么不当 cd
实际成功时,父 shell 不使用新目录吗?”
虽然采购您想要运行的脚本是一种解决方案,但您应该知道该脚本可以直接修改当前 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 目录书签。
您可以在 .bash_profile
中创建如下所示的函数,它会顺利运行。
以下函数采用一个可选参数,它是一个项目。例如,您可以运行
cdproj
或者
cdproj project_name
这是函数定义。
cdproj(){
dir=/Users/yourname/projects
if [ "$1" ]; then
cd "${dir}/${1}"
else
cd "${dir}"
fi
}
不要忘记来源您的 .bash_profile
这应该做你想要的。切换到感兴趣的目录(从脚本中),然后生成一个新的 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)
我做了以下事情:
创建一个名为 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
分别
在我的情况下,这条路要长得多——这些家伙早先用 ~ 信息总结了它。
cd
是多余且不雅的;别名应该只是 '. ~/case` 代替。此外,case
是保留关键字,因此是一个相当糟糕的名称选择。
如其他答案所述,您已更改目录,但仅在运行脚本的子外壳内。这不会影响父外壳。
一种解决方案是使用 bash 函数 而不是 bash 脚本 (sh
);通过将 bash 脚本代码放入函数中。这使得函数可以作为命令使用,然后,这将在没有子进程的情况下执行,因此任何 cd
命令都会影响调用者 shell。
重击功能:
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
快速编辑/创建这些文件
如何 :
将 bash 脚本代码复制到 bash 配置文件末尾的新函数中并重新启动终端,然后您可以运行 cdd
或您编写的任何函数。
脚本示例
使用 cdd
创建到 cd ..
的快捷方式
cdd() {
cd ..
}
ls 快捷方式
ll() {
ls -l -h
}
ls 快捷方式
lll() {
ls -l -h -a
}
如果您使用 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 文件)。
我有一个名为 p 的简单 bash 脚本来管理目录更改
github.com/godzilla/bash-stuff
只需将脚本放入本地 bin 目录 (/usr/local/bin)
并放入
alias p='. p'
在你的 .bashrc
您不需要脚本,只需设置正确的选项并创建环境变量。
shopt -s cdable_vars
在您的 ~/.bashrc
中允许 cd
到环境变量的内容。
创建这样一个环境变量:
export myjava="/home/tree/projects/java"
你可以使用:
cd myjava
注意讨论How do I set the working directory of the parent process?
它包含一些骇人听闻的答案,例如 https://stackoverflow.com/a/2375174/755804(通过 gdb 更改父进程目录,不要这样做)和 https://stackoverflow.com/a/51985735/755804(将 cd dirname 注入输入流的命令 tailcd
父进程的;嗯,理想情况下它应该是 bash 而不是 hack 的一部分)
这是一个老问题,但我真的很惊讶我在这里看不到这个技巧
而不是使用 cd 你可以使用
export PWD=the/path/you/want
无需创建子外壳或使用别名。
请注意,确保 /path/you/want 存在是您的责任。
我必须在 tcsh 中工作,我知道这不是一个优雅的解决方案,但是例如,如果我必须将文件夹更改为一个单词不同的路径,那么整个事情都可以在别名中完成
a alias_name 'set a = `pwd`; set b = `echo $a | replace "Trees" "Tests"` ; cd $b'
如果路径总是固定的,那么
a alias_name2 'cd path/you/always/need'
应该可以在上面的行中,设置了新的文件夹路径
. my-script
或source my-script
。