Shell Script 里的 cd 命令,很有点意思,有点困惑

2017-01-31 22:04:26 +08:00
 ericgui
下面代码都是为了说明问题,尽量简化了:
今天是这样的,我想写一个 script ,只有一行:
文件路径和名称:$PATH/cdtest.sh
#!/bin/bash
cd /data/someproject
也就是说,我想在任何目录下,直接跳转至指定目录(这里是 /data/someproject )
然后呢,自然就很显然没反应。只能用 source cdtest.sh 这个命令,才能实现跳转目录。
查了半天,才知道, script 执行的时候,创建了一个子 shell ,子 shell 的存在依赖于 current directory ,那显然就不能跳转目录了

现在问题来了,我做了这样的改变:
我先判断, pwd 是否是我的目标目录,如果是,就执行 git pull 命令,由于 git pull 命令必须在正确的 git directory 才能 pull 下来代码,所以如果目录不对,就产生 fatal error 。

文件路径和名称:$PATH/pullsomeproject.sh

1 #!/bin/bash
2
3 target='/data/someproject'
4
5 if [ $(pwd) = $target ]; then
6 git pull git@github.com:myaccount/someproject.git
7 else
8 cd /data/someproject
9 pullsomeproject.sh
10 fi


这个在任意目录下都可以执行成功。

说明什么?
说明在其他目录下,执行了 cd /data/someproject ,实现了目录跳转至 /data/someproject 这个目录,而且又执行了 pullsomeproject.sh 这个脚本。

但是,上面的代码,执行成功之后,仍然留在 pwd ,就是说,没有实现跳转目录。

所以这就尼玛困惑了。到底执行了 cd 这个命令么吗?如果没执行,那 git pull 怎么成功了呢(如果你在其他目录执行 git pull ,会有错误)
如果执行了,为啥没有实现跳转目录?

当然了,如果用 source pullsomeproject.sh ,那目录也跳转了, git pull 也执行了。
所以就感觉非常邪门。
7731 次点击
所在节点    Linux
18 条回复
hzlez
2017-01-31 22:19:18 +08:00
我理解,就和函数的入栈出栈一样,子 shell 调用结束,就回到你执行时的 current directory 了。
zwpaper
2017-01-31 22:20:06 +08:00
有点没看明白,但是
cd 只是在脚本执行的子 shell 里换目录了,按说也是可以执行成功的
git 在 2.几以后的版本可以用 -C 指定目录
xpol
2017-01-31 22:25:00 +08:00
git 1.8.5+ 就可以 git -C <directory> ... 了。
likuku
2017-01-31 22:25:08 +08:00
脚本里写 cd 是没问题的啊,我一直这么用,在 bash 环境 / bash some.sh 方式来显式执行。
wohenyingyu02
2017-01-31 22:30:37 +08:00
你都知道是新开的 shell 了, cd 跳转的是新开的 shell 的当前目录,不是你正在看的 shell 啊, pwd 也是检查新开的 shell 当前目录,执行完关闭新开的 shell ,为何会影响你在使用的 shell 呢
larsenlouis
2017-01-31 22:30:43 +08:00
#!/bin/bash
cd "$(realpath "/cygdrive/b/")"
ls
wohenyingyu02
2017-01-31 22:32:33 +08:00
@wohenyingyu02 好比你开了两个 shell 窗口,你在其中一个 cd xxx 并不会影响另一个
yyai3
2017-01-31 22:36:11 +08:00
subshell 继承原 shell 的环境变量和路径, subshell 里的 cd 及新增变量不会影响到原 shell
ericgui
2017-01-31 22:39:13 +08:00
@wohenyingyu02 哦,你这一解释我就明白了。 cd 之后新跳转的目录,只是我看不到而已。
ericgui
2017-01-31 22:40:38 +08:00
@wohenyingyu02 恩,是的,我看到的是 current directory , script 的子 shell 执行了 cd ,做了跳转,然后执行了 git pull

谢谢!豁然开朗!
ericgui
2017-01-31 22:41:47 +08:00
@yyai3
@wohenyingyu02 二位说的对。谢谢!
KentY
2017-02-01 00:06:34 +08:00
我的 pullall, 你可以参考. git 版本如果不是很老, 可以-C
https://github.com/sk1418/myScripts/blob/master/shell/pullall.sh
ericgui
2017-02-01 01:52:33 +08:00
@xpol 囧死了,谢谢。那就不用费劲判断目录了
binarylu
2017-02-01 01:54:25 +08:00
cd 不是命令,没有一个对应的 bin 程序, cd 是 shell 的关键字,由 shell 直接执行
webjin1
2017-02-01 02:34:11 +08:00
@binarylu cd 是 shell 内键命令
hosiet
2017-02-01 10:23:25 +08:00
我觉得直接把 cd 理解成系统调用比较好,直接对应 chdir(2),不是外部命令,只是运行中的 shell 改了改自己的工作目录而已。
owt5008137
2017-02-01 11:59:30 +08:00
1. 当前目录属于环境(变量)
2. 除了内建命令外, shell 里执行一个程序都是新开子进程的(包括执行一个脚本文件)
3. 子进程的环境(变量)变化不会影响父进程。

你理解了这三条就明白为什么了
ericgui
2017-02-01 15:37:39 +08:00
@owt5008137 谢谢,这次算是彻底明白了。非常感谢!

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/337540

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX