파트리스는 그의 대답 에서 문제의 원인을 확인 했지만 거기에서 어떻게 얻는 지 알고 싶다면 여기에 긴 이야기가 있습니다.
프로세스의 현재 작업 디렉토리는 너무 복잡하다고 생각하지 않습니다. 프로세스의 시스템 속성에서 프로세스가 호출 한 상대 경로가 시작되는 디렉토리 유형의 파일에 대한 핸들 인 프로세스의 속성입니다. 상대 경로를 해결할 때 커널은 (a) 현재 디렉토리의 전체 경로를 알 필요가 없으며 상대 경로의 첫 번째 구성 요소를 찾기 위해 해당 디렉토리 파일의 디렉토리 항목을 읽습니다 ( ..다른 경로와 유사 함) 그 점에서 파일)을 계속하고 거기에서 계속됩니다.
이제는 사용자로서 때때로 디렉토리 트리에서 디렉토리가 어디에 있는지 알고 싶어합니다. 대부분의 Unices에서 디렉토리 트리는 루프가없는 트리입니다. 즉, 트리의 루트 ( /)에서 지정된 파일 까지의 경로는 하나뿐입니다 . 이 경로는 일반적으로 정식 경로라고합니다.
프로세스가 그냥 도보 무슨 상관이 현재 작업 디렉토리의 경로를 얻으려면 (물론 아래 는 바닥에 뿌리를 가진 나무를보고 싶은 경우) 노드의 이름을 찾는 루트에 다시 나무를 도중에.
예를 들어, 현재 디렉토리가이라는 것을 찾으려고하는 프로세스 /a/b/c는 ..디렉토리를 열고 (상대 경로도 ..현재 디렉토리의 항목) 디렉토리와 같은 inode 번호를 가진 디렉토리 유형의 파일을 .찾습니다. c를 찾은 다음 ../..찾을 때까지 계속 열립니다 /. 거기에 모호성이 없습니다.
즉, 무엇 getwd()이나 getcwd()C의 기능을 수행하거나 적어도 수행하는 데 사용됩니다.
현대 리눅스와 같은 일부 시스템에는 커널 공간에서 조회를 수행하는 현재 디렉토리로의 표준 경로를 반환하는 시스템 호출이 있습니다 (모든 구성 요소에 대한 읽기 권한이 없어도 현재 디렉토리를 찾을 수 있습니다) 그것이 바로 getcwd()전화입니다. 최신 Linux에서는 readlink ()를 통해 현재 디렉토리의 경로를 찾을 수도 있습니다 /proc/self/cwd.
이것이 현재 디렉토리의 경로를 반환 할 때 대부분의 언어와 초기 쉘이하는 일입니다.
귀하의 경우에는, 당신은 호출 할 수 있습니다 cd a당신이 원하는대로에 심볼릭 링크 때문에, 수도 등의 시간을 .현재 디렉토리 그래서 모든 변경되지 않습니다, getcwd(), pwd -P, python -c 'import os; print os.getcwd()', perl -MPOSIX -le 'print getcwd'당신의 반환합니다 ${HOME}.
이제 심볼릭 링크가 모든 것을 복잡하게 만들었습니다.
symlinks디렉토리 트리에서 점프를 허용합니다. 에서 /a/b/c, 경우 /a나 /a/b또는 /a/b/c의 다음 정식 경로 심볼릭 링크이며, /a/b/c완전히 다른 무언가를 할 것이다. 특히의 ..항목 /a/b/c이 반드시 그런 것은 아닙니다 /a/b.
Bourne 쉘에서 다음을 수행하십시오.
cd /a/b/c
cd ..
또는:
cd /a/b/c/..
에 끝날 것이라는 보장은 없습니다 /a/b.
처럼:
vi /a/b/c/../d
반드시 다음과 같을 필요는 없습니다.
vi /a/b/d
ksh논리적 인 현재 작업 디렉토리 개념을 도입하여 어떻게 든 해결할 수 있습니다. 사람들은 그것에 익숙해졌고 POSIX는 그 동작을 지정하여 결국 요즘 대부분의 쉘에서도 그렇게합니다.
의 경우 cd와 pwd(내장 명령 만 그들을 위해 (도에 대해는 비록 popd/ pushd을)이 포탄), 쉘은 현재 작업 디렉토리의 자신의 아이디어를 유지한다. $PWD특수 변수에 저장됩니다 .
할 때 :
cd c/d
하더라도 c또는 c/d동시에 심볼릭이다 $PWD는 containes은 /a/b, 그것이 추가 c/d단부에 그렇게 $PWD된다 /a/b/c/d. 그리고 당신이 할 때 :
cd ../e
일을 대신에 chdir("../e"), 그렇습니다 chdir("/a/b/c/e").
그리고 pwd명령은 $PWD변수 의 내용 만 반환합니다 .
때문 대화 형 쉘에서 유용 pwd당신이 거기에 도착하는 방법에 대한 정보를 제공하고 한 경우에만 사용으로 현재 디렉토리 경로 출력 ..에 대한 인수 cd및 기타되지 명령, 그것은 당신을 놀라게 할 가능성이 낮아을, 때문에 cd a; cd ..또는 cd a/..것은 일반적으로 당신에게 돌아 당신이 있던 곳으로.
이제는 $PWD하지 않으면 수정되지 않습니다 cd. 다음에 cd또는을 ( 를) 호출 할 때까지 pwd많은 일이 발생할 $PWD수 있으며 구성 요소 이름을 바꿀 수 있습니다. 현재 디렉토리는 절대 변경되지 않지만 (삭제 될 수는 있지만 항상 동일한 inode 임) 디렉토리 트리의 경로는 완전히 변경 될 수 있습니다. getcwd()디렉토리 트리를 내려 가면서 호출 될 때마다 현재 디렉토리를 계산하여 정보가 항상 정확하지만 POSIX 쉘로 구현 된 논리 디렉토리의 경우 정보 $PWD가 오래 될 수 있습니다. 그래서 실행에 cd또는 pwd일부 포탄은 방지 할 수 있습니다.
특정 인스턴스에서 다른 쉘을 가진 다른 동작을 볼 수 있습니다.
일부 등 ksh93문제를 완전히 무시하고, 그래서 당신은 전화 후에도 잘못된 정보를 반환합니다 cd(당신은 당신이보고있는 동작 볼 것 bash거기를).
어떤 사람들은 그것이 현재 디렉토리에 대한 경로인지 확인 bash하거나 zsh확인 하지는 않습니다 .$PWDcdpwd
pdksh 같은 두에 확인 않습니다 pwd와 cd(하지만,시 pwd, 업데이트하지 않습니다 $PWD)
ash(적어도 데비안에서 찾은 것)은 확인하지 않으며 , 그렇게 할 cd a때 실제로 cd "$PWD/a"하므로 현재 디렉토리가 변경되어 $PWD더 이상 현재 디렉토리를 가리 키지 않으면 실제로 a는 현재 디렉토리 의 디렉토리로 변경되지 않습니다 이지만 그 중 하나에 $PWD오류가 있으면 오류를 반환합니다.
당신이 그것을 가지고 놀고 싶다면, 당신은 할 수 있습니다 :
cd
mkdir -p a/b
cd a
pwd
mv ~/a ~/b
pwd
echo "$PWD"
cd b
pwd; echo "$PWD"; pwd -P # (and notice the bug in ksh93)
다양한 껍질에.
귀하의 경우에는, 당신은 사용하고 있기 때문에 bash후 cd a, bash확인 $PWD여전히 현재 디렉토리를 가리 킵니다. 그렇게하기 위해서는 호출 stat()의 값에 $PWD그 아이 노드 번호를 확인하고 그와 비교하는 ..
그러나 $PWD경로를 찾는 데 너무 많은 심볼릭 링크를 해결 stat()하면 오류와 함께 반환되므로 쉘은 $PWD여전히 현재 디렉토리에 해당 하는지 여부를 확인할 수 없으므로 다시 계산하여 getcwd()업데이트합니다 $PWD.
이제 Patrice의 답변을 명확히하기 위해 경로를 찾는 동안 발생하는 심볼릭 링크 수를 확인하는 것은 심볼릭 링크 루프를 방지하는 것입니다. 가장 간단한 루프는
rm -f a b
ln -s a b
ln -s b a
안전 장치가 없으면 cd a/x시스템은에 대한 a링크를 찾아야하며 링크를 찾고 링크를 b하는 심볼릭 링크이며 a, 무한정 계속됩니다. 이를 막는 가장 간단한 방법은 임의의 수의 심볼릭 링크를 초과하여 해결 한 후 포기하는 것입니다.
이제 논리적 인 현재 작업 디렉토리로 돌아가서 왜 그렇게 좋지 않은 기능이 되었습니까? cd다른 명령이 아닌 셸 에서만 사용된다는 것을 인식하는 것이 중요 합니다.
예를 들어 :
cd -- "$dir" && vi -- "$file"
항상 다음과 같은 것은 아닙니다.
vi -- "$dir/$file"
그렇기 때문에 사람들이 cd -P혼란을 피하기 위해 항상 스크립트에서 사용하는 것이 좋습니다 ( ../x다른 언어 대신 쉘로 작성 되었기 때문에 소프트웨어가 다른 명령 과 다르게 인수를 처리하기를 원하지 않는 경우가 있습니다).
-P옵션은 비활성화하는 것입니다 논리적 디렉토리 그렇게 처리 cd -P -- "$var"호출 않는 사실 chdir()의 내용에 $var(때를 제외을 $var하다 -그 다른 이야기에 불과). 그리고 후 cd -P, $PWD정식 경로가 포함됩니다.