我一直想知道为什么cd不是程序,但从未设法找到答案。

谁知道为什么会这样?

评论

另请参阅内置命令与非内置命令有什么区别?

我记得读过(我找不到哪里)原始的unix cd命令是一个单独的程序。外壳程序专门处理它,因为它不分叉,而只是执行。当cd完成后,它将执行sh。我不知道这是不是真实的故事。

重点是什么?如果要添加特殊处理,则最好只调用chdir syscall。来源:v1 v5 v7(带有Bourne shell的第一版)

@camh,这是一个真实的故事。我在丹尼斯·里奇(Dennis M. Ritchie)撰写的一篇文章中也读到了这本书,“ Unix分时系统的演变”,AT&T贝尔实验室技术期刊63(6),第2部分,1984年10月。
@Mikel:我同意这似乎毫无意义,但我只是在讲一个我读过的关于CD的故事。既然@jlliagre填写了详细信息,我对此方面显然是错误的。

#1 楼

cd命令修改“当前工作目录”,对吗?

“当前工作目录”是每个进程唯一的属性。

因此,如果cd是一个程序将像这样运行:


cd foo
cd进程启动
cd进程更改了cd进程的目录cd进程退出
您的shell仍具有与开始之前相同的状态,包括当前的工作目录。


评论


您的五个步骤是正确的,但是“如果cd是一个程序,它将像这样工作”应该是“当在外部程序实现中使用cd时,它确实会这样工作”。

– jlliagre
2012年5月19日在12:21

我不是系统程序员,也不是真正了解与shell交互的来龙去脉,所以我希望shell公开其当前的工作目录,而cd则是访问和更改该属性的程序。在看了这个答案之后,要理解,由于许多原因,这可能并不是其实际工作方式的最佳选择。

–詹森
2014年10月31日在18:48

#2 楼

cd除了是内置的shell外,实际上也是POSIX兼容OS上的程序。他们必须为常规实用程序(例如cd)提供独立的可执行文件。例如,对于Solaris,AIX,HP-UX和OSX。

显然,内置的cd仍然是必需的,因为其外部实现不会更改当前的shell目录。但是,后者仍然有用。这是一个示例,显示POSIX如何预想如何使用此cd命令:不允许进入cd。在大多数Gnu / Linux发行版中,它均失败,但显示以下错误消息: cd不是程序吗?”由最初的Unix合著者之一撰写。在非常早的Unix实现中,cd(当时的拼写为chdir)是一个外部程序。在第一次实施fork之后,它只是突然停止工作。

引用丹尼斯·里奇(Dennis Ritchie):当前目录)命令已停止工作。关于添加fork可能如何破坏chdir调用,有大量的代码阅读和焦虑的内省。最终,真理浮出水面:在旧系统中,chdir是一个普通命令;它调整了附加到终端的(唯一)进程的当前目录。在新系统下,chdir命令正确地更改了创建的进程的当前目录以执行该进程,但是该进程立即终止,并且对其父外壳没有任何影响!有必要使chdir成为特殊命令,该命令在shell内部执行。事实证明,几个类似命令的功能具有相同的属性,例如login。


来源:Dennis M. Ritchie,“ Unix分时系统的演进”,AT&T贝尔实验室技术期刊63(6),第2部分,1984年10月,第1577–93页,
由于创建了一个新进程来执行每个命令,因此如果将其作为普通的
命令编写,chdir将无效。 。因此,它被
Shell识别并执行。

评论


...因此,很明显,POSIX要求必须有一个独立的cd可执行文件,但它什么也不做(除非使用错误的参数调用可能会发出错误消息)。奇怪的。

–伊尔马里·卡洛宁(Ilmari Karonen)
2012年5月16日21:39



哦,如果是真的,那不是POSIX中最愚蠢的事情。

–卡兹
2012年5月16日23:06

POSIX cd页面还说:“由于cd影响当前的shell执行环境,因此它总是作为shell常规内置文件提供。”

– Mikel
2012年5月17日,0:57

@Kaz,它们不是完全不同的东西。他们做同样的事情,但是只有内置的会影响当前的shell。

– jlliagre
2012年5月17日5:32



@Kaz:请不要在我只报告一个事实的时候傻叫我。您可能同意或不同意POSIX,但不开枪。

– jlliagre
2012年5月17日下午5:37

#3 楼

从Bash简介(什么是外壳程序)开始:


外壳程序还提供了一小套内置命令(内建程序)
,实现了无法通过或无法获得的功能
单独的实用程序。例如,无法在外壳程序外部实现cdbreakcontinue
exec,因为它们直接操作外壳程序本身。可以在单独的实用程序中实现historygetopts
killpwd内置插件,但它们更易于用作内置命令。所有的shell内建函数将在随后的
部分中介绍。

#4 楼

对于今年的愚人节,我编写了独立版本的cd

没有人笑话。感叹。

不确定要在外壳中内置cd的任何人都应下载,构建并尝试。 :)

评论


真有用的代码! :-)

– dschulz
2012年5月17日下午5:13

很高兴看到有人在努力使Gnu / Linux更符合POSIX。您的实现不仅是一个很好的笑话,而且实际上是Linux发行版中缺少的一些东西...

– jlliagre
2012年5月17日下午6:30

我认为明年我将再次引用POSIX问题进行尝试。 ;)

–沃伦·杨(Warren Young)
2012年5月17日在7:03

6年后:好吧,是吗?

–彼得-恢复莫妮卡
18年11月20日在15:55

@ PeterA.Schneider:我以为很明显我在开玩笑,所以要明确,不,我实际上不会花很多力气将其投入到当前的OS和类似OS的项目中,例如Cygwin缺少/ bin / cd。如果您想采用我的代码并自行完成自己的任务,欢迎您这样做。

–沃伦·杨(Warren Young)
18-11-20在16:01



#5 楼

Shell中的cd命令不能是单独的进程,因为在Unix中,没有机制可以更改其他进程(甚至是父进程)的当前工作目录。

如果cd是一个不同的进程,则它将不得不更改其父级(shell)的当前工作目录,这在Unix中是不可能的。
cd是一种特殊的内置命令。 Shell调用诸如chdir()fchdir()之类的函数来更改其自己的当前工作目录。

注:内核为每个进程存储当前工作目录的索引节点号。子进程从其父进程继承它的cwd

#6 楼

cd是shell内置命令。就这么简单。 CD的人说了这一切。 cd命令更改所有解释器和(在线程环境中)所有线程的工作目录。

评论


因为外壳程序是一个环境,它关心您当前的工作目录($ PDW ...)或cdable_vars。最终,此内置方法是所有用户可见命令都应更改当前工作目录的方式。您可以通过以下方式进行测试:在不使用cd.c的情况下编译bash并尝试编写自己的cd脚本,该脚本尝试处理所有环境cdable_vars。这个问题也与开发人员有关。我敢打赌他们可以更详细地回答您这个问题。

–user18925
2012年5月17日16:11

cd是内置的,这是一个很好的技术原因。我建议您阅读排名最高的答案,并考虑如何改善您的答案。

–索比昂·拉文·安德森(ThorbjørnRavn Andersen)
2012年5月17日下午16:22

排名最高的答案是我读过的最糟糕的答案!可是我是谁!

–user18925
2012年5月17日下午16:32

但这回答了为什么的问题。

–索比昂·拉文·安德森(ThorbjørnRavn Andersen)
2012年5月18日晚上11:21

#7 楼

我认为人们回答中缺少的一件事是当前目录是每个程序都可以更改的环境变量。如果使用“导出”命令查看当前环境变量列表,则结果中将具有:

declare -x PWD="/home/erfan"



因此通过“ cd”命令我们只想修改此内部变量。
我想,如果尝试这样做,我们当然可以在shell中更改任何pty的PWD变量。
像: br />
,但我认为在正常情况下是没有必要的。

评论


的确,Bourne Shell将当前工作目录(CWD)公开为$ PWD,但这不是主要的存储位置。实际位置在内核的每个进程结构中。因此,说CWD“是环境变量”是不正确的。如果它按照您建议的方式工作,则此C两行代码将打印..路径,而不是您从其开始的路径:#include int main(void){chdir(“ ..”); puts(getenv(“ PWD”)); }(顺便说一下,C外壳将CWD公开为%cwd。)

–沃伦·杨(Warren Young)
2012年5月23日16:59



让我们向您的应用添加其他几行。 #include int main(void){chdir(“ ..”); puts(getenv(“ PWD”)); setenv(P“ PWD”,“ /”,1); puts(getenv(“ PWD”)); }结果将是什么?

– Erfankam
2012年5月25日在7:52

这只会覆盖变量的值,而对CWD没有副作用。这是一个更好的测试,它表明:#include int main(void){char ac [99]; setenv(“ PWD”,“ /”,1); puts(getcwd(ac,sizeof(ac))); }它将显示您从中启动程序的目录,而不是/。

–沃伦·杨(Warren Young)
2012年5月25日晚上8:02

我认为每个进程也都具有工作目录和路径变量。因此,您可以通过chdir更改进程的此属性。 Shell也具有此属性,并且通过cd我们修改此属性。

– Erfankam
2012年5月25日晚上8:56

不,我告诉您$ PWD仅对Bourne Shell具有意义。这只是Shell与Shell脚本进行通讯的一种方式,因此他们不必调用pwd即可找到它。任何依赖于$ PWD的值的独立程序都是不可靠的。

–沃伦·杨(Warren Young)
2012年5月25日上午9:26