파트리스는 그의 대답 에서 문제의 원인을 확인 했지만 거기에서 어떻게 얻는 지 알고 싶다면 여기에 긴 이야기가 있습니다.
프로세스의 현재 작업 디렉토리는 너무 복잡하다고 생각하지 않습니다. 프로세스의 시스템 속성에서 프로세스가 호출 한 상대 경로가 시작되는 디렉토리 유형의 파일에 대한 핸들 인 프로세스의 속성입니다. 상대 경로를 해결할 때 커널은 (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
확인 하지는 않습니다 .$PWD
cd
pwd
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
정식 경로가 포함됩니다.