当我创建自己的shell时,我无法执行cd命令,而该命令在Linux shell中是可以执行的。为什么会这样?
这可能是因为cd
命令必须内置到外壳中,而不是外部的并执行。如果外部命令更改了目录,则它对父外壳无效。 (即使在Linux和macOS系统上通常使用命令/bin/cd
或/usr/bin/cd
,执行该命令也会更改该进程的目录,但对调用它的进程没有影响。)
我不理解“如果外部命令更改了目录,则对父外壳无效”。
[通常,shell执行命令时,它将执行fork()
,并且子进程使用exec()
执行用户输入的命令。例如,如果输入的命令为'ls /
',则Shell安排使用两个参数/bin/ls
和ls
执行/
。但是,如果选择的命令执行chdir()
系统调用,则将影响子进程,但不影响父Shell。因此,外壳程序必须自己处理cd
命令,而不是通过fork()
和exec()
。
[请注意,在DOS中,.BAT
文件可以执行cd
,它会影响cmd.exe
进程。在Unix中不会发生这种情况-子进程不会影响父进程的当前目录。
Jonathan Leffler解释了为什么会这样,但是我想提供一种解决方法,以防您确实需要此功能。在bash中(您未指定,所以我假设),source
命令可用于在CURRENT Shell进程中执行Shell脚本。我使用类似于下面的内容(虽然更全面)以及shell别名来更改项目目录并自动设置环境:
~:$ cat $HOME/bin/goproj
#!/bin/bash
...
export SOMEVAR=someval
cd /home/foo/src/projects/"$1"
...
~:$ alias gp
alias gp="source $HOME/bin/goproj"
~:$ gp foo
~/src/projects/foo:$ echo $SOMEVAR
someval
~/src/projects/foo:$
使用这种类型的设置,您可以使用要采购的脚本中存在的任何内容来修改当前shell。请注意,如果直接运行“ goproj”,它将无法解决您已经遇到的同一问题;您必须使用source
对其进行调用。
这很简单:
cd
不是命令。尝试一下:
-whereis ls
-whereis cd
(查看区别)
cd
是外壳的属性,因此,如果要制作外壳,则必须支持cd
。这样看,当执行ls时,它需要知道pwd。因此,它将是您处理目录的自定义外壳程序。因此,它是必须支持cd的外壳。
我想我已经说清楚了。