cd는 왜 프로그램이 아닌가?


128

나는 왜 cd프로그램이 아닌지 항상 궁금 했지만 답을 찾지 못했습니다.

왜 이것이 사실인지 아는 사람이 있습니까?



1
원래 유닉스 cd명령이 별도의 프로그램 이라는 것을 읽은 것을 기억합니다 (어디를 찾을 수 없습니다) . 쉘은하지 않았다 특별히에 있음을 처리 fork단지 exec. 그리고 cd완료되면 exec sh. 이것이 사실인지 모르겠습니다.
camh

요점이 뭐야? 특별한 처리를 추가하려면 chdirsyscall을 호출하십시오 . 출처 : v1 v5 v7 (Bourne 쉘이있는 첫 번째 버전)
Mikel

2
@ camh, 그것은 진실한 이야기입니다. AT & T Bell Laboratories 기술 저널 63 (6), Part 2, 1984 년 10
jlliagre

@Mikel : 나는 그것이 무의미 해 보이지만, cd나는 내가 읽은 것에 대한 이야기를 전달하고 있었다. @jlliagre가 세부 사항을 채 웠기 때문에 나는 그것의 측면에 대해 분명히 틀렸다.
camh

답변:


171

cd명령은 "현재 작업 디렉토리"를 수정합니까?

"현재 작업 디렉토리"는 각 프로세스에 고유 한 특성입니다.

따라서 cd프로그램이라면 다음과 같이 작동합니다.

  1. cd foo
  2. cd프로세스가 시작됩니다
  3. cd프로세스는 디렉토리 변경 은 CD 프로세스를
  4. cd프로세스가 종료
  5. 쉘은 여전히 ​​현재 작업 디렉토리를 포함하여 시작하기 전과 동일한 상태를 유지합니다.

8
5 단계는 정확하지만 " cd프로그램 인 경우 다음과 같이 작동합니다"는 " cd외부 프로그램 구현에 사용될 때 이와 같이 작동합니다"여야합니다 .
jlliagre

1
시스템 프로그래머가 아니거나 쉘과의 상호 작용에 대한 깊은 지식과 지식을 가지고 있지 않다면 쉘이 현재 작업 디렉토리를 노출하고 cd가 해당 속성에 액세스하고 변경하는 프로그램이 될 것으로 기대했을 것입니다. 이 답변을 살펴본 후 실제로 여러 가지 이유로 작동하는 방식에 비해 최적이 아님을 이해하십시오.
Jason

108

cd쉘 내장 외에도 POSIX 호환 OS에 대한 프로그램이기도합니다 . 이들은 같은 일반 유틸리티를위한 독립적 인 실행 파일을 제공 해야합니다cd . 예를 들어 Solaris , AIX , HP-UX 및 OS X의 경우 입니다.

분명히 cd외부 구현은 현재 쉘 디렉토리를 변경하지 않으므로 내장 은 여전히 ​​필수입니다. 그러나 후자는 여전히 유용 할 수 있습니다. 다음은 POSIX가이 cd명령을 사용 하는 방법을 상상하는 방법을 보여주는 예입니다 .

find . -type d -exec cd {} \;

POSIX 시스템에서이 oneliner는 허용되지 않는 모든 디렉토리에 대한 오류 메시지를보고합니다 cd. 대부분의 Gnu / Linux 배포에서는 다음과 같은 오류 메시지와 함께 실패합니다.

find: `cd': No such file or directory

그리고 원래 Unix 공동 저자 중 한 명이 " 왜 CD가 프로그램이 아닌가? " 라는 질문에 대한 답이 있습니다 . 초창기의 유닉스 구현 cd( chdir그 당시 철자 )은 외부 프로그램이었습니다. fork처음 구현 된 후 예기치 않게 작동이 중지되었습니다 .

인용 데니스 리치 :

우리의 환대 중에 chdir (현재 디렉토리 변경) 명령이 작동을 멈췄다는 것이 발견되었습니다. 포크의 추가가 chdir 호출을 어떻게 깨뜨릴 수 있었는지에 대한 많은 코드 읽기와 불안한 내성도있었습니다. 마침내 진실은 시작되었다. 구 시스템에서 chdir은 일반적인 명령이었다. 터미널에 연결된 (고유 한) 프로세스의 현재 디렉토리를 조정했습니다. 새 시스템에서 chdir 명령은 실행하기 위해 작성된 프로세스의 현재 디렉토리를 올바르게 변경했지만이 프로세스는 즉시 종료되었으며 상위 쉘에는 아무런 영향을 미치지 않았습니다! chdir을 쉘 내부에서 실행되는 특수 명령으로 만들어야했습니다. 로그인과 같은 몇 가지 명령과 같은 기능은 동일한 속성을 가지고 있습니다.

출처 : Dennis M. Ritchie,“ 유닉스 시간 공유 시스템의 진화 ”, AT & T Bell Laboratories 기술 저널 63 (6), 2 부, 1984 년 10 월, pp.1577–93

유닉스 버전 1 (1971 년 3 월) chdir 매뉴얼 페이지 상태 :

각 명령을 실행하기 위해 새 프로세스가 작성되므로 chdir이 일반 명령으로 작성된 경우에는 효과가 없습니다. 따라서 Shell에 의해 인식되고 실행됩니다.


10
POSIX는 독립 cd실행 파일 이 있어야 하지만 아무것도하지 않아야합니다 (잘못된 인수로 호출 된 경우 오류 메시지를 낼 수는 없습니다). 기묘한.
Ilmari Karonen

4
글쎄, 그것이 사실이라면 POSIX에서 가장 어리석은 일은 아닙니다.
Kaz

5
POSIX CD 페이지는 또한 "CD는 현재 쉘 실행 환경에 영향을 미치는 때문에, 항상 쉘 정규 내장으로 제공됩니다."말했다.
Mikel

6
@Kaz, 그들은 완전히 다른 것이 아닙니다. 그들은 똑같은 일을하지만 내장 된 것만 현재 쉘에 영향을 미칩니다.
jlliagre

13
@ Kaz : 사실을보고하는 동안 바보라고 부르지 마십시오. POSIX에 동의하거나 동의하지 않을 수 있지만 메신저를 쏘지 마십시오.
jlliagre

47

Bash 소개에서 ( 쉘이란 무엇입니까? ) :

쉘은 또한 별도의 유틸리티를 통해 얻을 수 없거나 불편한 기능을 구현하는 작은 내장 명령 세트 (내장)를 제공합니다. 예를 들어, cd, break, continue, 및 exec그들이 직접 쉘 자체를 조작하기 때문에), 쉘의 외부에 구현 될 수 없다. 는 history, getopts, kill, 또는 pwd내장 매크로는, 다른 사람의 사이에서, 별도의 유틸리티에서 구현 될 수 있지만, 그들은 같은 내장 명령을 사용하는 것이 더 편리합니다. 모든 쉘 내장은 다음 섹션에서 설명합니다.


29

올해 만우절 에 독립형 버전을cd 작성 했습니다 .

아무도 농담을받지 못했습니다. 한숨.

cd쉘에 내장되어 있는지 확실하지 않은 사람 은 다운로드하여 빌드하고 시도해야합니다.

맨 페이지도 읽으십시오. :)


정말 유용한 코드! :-)
dschulz

6
Gnu / Linux를 POSIX 호환으로 만드는 일을하는 누군가를 만나게되어 반갑습니다. 당신의 구현은 좋은 농담 일뿐만 아니라 실제로 리눅스 배포판에서 빠진 것입니다.
jlliagre

8
POSIX 문제를 인용하여 내년에 다시 시도 할 것입니다. ;)
Warren Young

6 년 후 : 글쎄요?
피터 A. 슈나이더

@ PeterA.Schneider : 농담이 분명하다고 생각했습니다. 아니면 분명합니다. 현재 Cygwin과 같은 OS 및 OS와 같은 프로젝트 에이 작업을 시도하는 데 많은 노력을 기울이지 않을 것입니다. 부족하다 /bin/cd. 내 코드를 가져 와서 자신의 개인적인 퀘스트를 만들고 싶다면 언제든지 환영합니다.
워렌 영

4

cd유닉스에서는 다른 프로세스의 현재 작업 디렉토리를 변경하는 메커니즘이 없기 때문에 쉘 의 명령은 별도의 프로세스가 될 수 없습니다 (부모 프로세스조차 포함하지 않음).

경우 cd다른 프로세스이었다 그것은 유닉스 수없는 부모 (쉘)의 현재 작업 디렉토리를 변경해야합니다. 대신 cd특수 내장 명령입니다. 쉘 은 자신의 현재 작업 디렉토리 chdir()와 같은 기능을 호출 하고 fchdir()변경합니다.

참고 : 커널은 모든 프로세스에 대한 현재 작업 디렉토리의 inode 번호를 저장합니다. 자식 프로세스는 부모 프로세스를 상속받습니다 cwd.


0

cd는 쉘 내장 명령입니다. 있는 그대로. 남자 CD는 모든 것을 말합니다. cd 명령은 모든 인터프리터 및 스레드 환경에서 모든 스레드의 작업 디렉토리를 변경합니다.


쉘은 현재 작업 디렉토리 ($ PDW ...) 또는 cdable_vars를 처리하는 환경이기 때문입니다. 이 내장은 궁극적으로 모든 사용자가 볼 수있는 명령이 현재 작업 디렉토리를 변경하는 방식입니다. cd.c없이 bash를 컴파일하고 자신의 cd 스크립트를 작성하여 모든 환경 cdable_vars를 처리하려고 시도합니다. 이 질문은 또한 개발자와 관련이 있습니다. 나는 그들이 당신 에게이 질문에 더 자세히 대답 할 수 있다고 확신합니다.

2
내장 된 매우 좋은 기술적 이유가 cd있습니다. 가장 높은 순위의 답변을 읽고 답변을 개선 할 수있는 방법을 고려해보십시오.
Thorbjørn Ravn Andersen 16:17에

가장 높은 순위의 답변은 내가 읽은 최악의 내용이었습니다! 그러나 응? 내가 누구야!

3
그러나 질문에 대답합니다 .
Thorbjørn Ravn Andersen

-1

사람들이 대답에서 누락 한 가지는 현재 디렉토리가 각 프로그램이 변경할 수있는 환경 변수라는 것입니다. 'export'명령을 사용하여 현재 환경 변수 목록을 보면 다음과 같은 이점이 있습니다.

declare -x PWD="/home/erfan"

당신의 결과에서. 따라서 'cd'명령으로이 내부 변수를 수정하려고합니다. 우리가 시도하면 물론 모든 pty의 PWD 변수를 쉘에 넣을 수 있다고 생각합니다. 처럼:

cder    #change current PTY $PWD variable

그러나 정상적인 경우에는 필요가 없다고 생각합니다. 다시 말해, bash (또는 모든 쉘)의 도움을 받아 정의 된 내부 변수를 수정합니다.


3
Bourne 쉘이 현재 작업 디렉토리 (CWD)를 $ PWD로 노출하는 것은 사실이지만, 이는 기본 스토리지 위치가 아닙니다. 실제 위치는 커널의 프로세스 별 구조에 있습니다. 따라서 CWD가 "환경 변수"라고 말하는 것은 올바르지 않습니다. 그것이 제안한 방식으로 작동한다면,이 C 2 라이너는 ..경로를 시작한 경로가 아닌 경로를 인쇄합니다 . #include <stdlib.h> int main(void) { chdir(".."); puts(getenv("PWD")); }(C 쉘은 CWD를 대신 % cwd로 노출시킵니다.)
Warren Young

앱에 다른 줄을 추가 할 수 있습니다. #include <stdlib.h> int main (void) {chdir ( ".."); 풋 (getenv ( "PWD")); setenv (P "PWD", "/", 1); 풋 (getenv ( "PWD")); } 결과로 무엇을 얻게됩니까?
Erfankam

3
CWD에 부작용없이 변수의 값을 덮어 씁니다. 이것은 다음을 보여주는 더 좋은 테스트입니다. #include <unistd.h> int main(void) { char ac[99]; setenv("PWD", "/", 1); puts(getcwd(ac, sizeof(ac))); }프로그램을 시작한 디렉토리가 아니라 표시됩니다 /.
워렌 영

모든 프로세스에는 작업 디렉토리와 경로 변수가 있다고 생각합니다. 따라서 chdir에 의해 프로세스의이 속성을 변경하면됩니다. Shell도이 속성을 가지고 있으며 cd로이 속성을 수정합니다.
Erfankam

4
아니요, $PWDBourne 쉘에만 의미가 있다고 말하고 있습니다 . 쉘이 알고있는 것을 쉘 스크립트와 통신 할 수있는 방법 일 뿐이므로이를 pwd찾기 위해 호출 할 필요가 없습니다. 가치에 따른 독립형 프로그램 $PWD은 신뢰할 수 없습니다.
워렌 영
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.