빌드노트
Bash에서 cd 뒤 pwd를 받았는데 경로가 두 줄이다
CDPATH로 디렉터리를 찾은 cd는 성공해도 경로를 표준출력에 쓴다. cd와 pwd를 함께 명령 치환으로 받았을 때 생기는 두 줄을 확인하고, 자식 안에서 CDPATH를 비우거나 ./project로 현재 위치의 경로를 지정한다.
Bash 스크립트에서 destination=$(cd project && pwd -P)로 경로를 구했는데 값이 두 줄로 들어갈 수 있다. 그 값에 파일 이름을 붙이면 실제로 존재하는 파일도 찾지 못한다. CDPATH 검색으로 이동한 cd가 경로를 한 번 출력하고, 뒤의 pwd가 같은 경로를 다시 출력하기 때문이다. 현재 위치의 project가 목적지라면 ./project로 지정하거나, 명령 치환 안에서 CDPATH를 비워 검색의 영향을 없앤다.
변수에 담기기 전부터 경로가 두 번 출력된다
Linux나 WSL의 Bash에서 문제가 생기는 스크립트의 경로 계산 부분을 다음처럼 확인한다. project는 이동할 실제 디렉터리 이름으로 바꾼다. 스크립트가 실행되는 것과 같은 작업 위치에서 확인해야 한다. 출력의 <와 >는 값의 경계를 드러내기 위한 표시이며, 값 자체에는 들어가지 않는다.
destination=$(cd -- project && pwd -P)
status=$?
printf 'status=%s\ndestination=<%s>\n' "$status" "$destination"
별도 실습에서는 work/project와 lookup/project를 만들고 work에서 시작했다. CDPATH에는 lookup의 절대경로 하나만 넣었다. Bash 5.2.21에서 위 명령을 실행한 결과다. 출력의 …는 긴 공통 절대경로 앞부분만 줄인 표시다.
status=0
destination=<…/lookup/project
…/lookup/project>
이동은 성공했지만, destination에는 두 경로 사이의 개행도 들어 있다. "$destination/marker.txt"처럼 큰따옴표를 붙여도 그 개행까지 포함한 하나의 파일 경로가 된다. 실습에서 lookup/project/marker.txt는 존재했지만, 이 값으로 조회한 파일 존재 검사는 실패했다.
같은 위치와 설정에서 (cd -- project)만 실행해도 경로 한 줄이 나왔다. pwd를 실행하기 전에 이미 출력이 있었던 것이다. Bash의 cd 문서 (새 탭에서 열림)는 CDPATH의 비어 있지 않은 검색 항목을 사용해 이동에 성공하면 새 작업 디렉터리의 절대경로를 표준출력에 쓴다고 설명한다. CDPATH가 설정돼 있다는 사실만으로 항상 출력하는 것은 아니다.
CDPATH는 cd가 디렉터리를 찾을 때 쓰는 검색 목록이다. 여러 항목은 콜론으로 구분한다. 명령 실행 파일을 찾는 PATH와는 별개다. 변수의 정의는 Bourne Shell Variables (새 탭에서 열림)에 있다. 이번에는 현재 위치에도 project가 있었지만, cd project가 검색 목록의 다른 project로 이동했다는 점도 함께 확인했다.
현재 위치의 project를 의도했다면 검색을 끈다
스크립트가 자기 작업 위치를 기준으로 project를 찾아야 한다면, 경로를 구하는 자식 범위에서만 CDPATH를 비운다. 다음 코드는 이동과 pwd가 성공한 경우에만 후속 파일 경로를 만든다.
if destination=$(CDPATH=; cd -- project && pwd -P); then
printf '%s\n' "$destination/marker.txt"
else
printf 'project 디렉터리의 경로를 구하지 못했습니다.\n' >&2
fi
같은 실습 조건에서 이번 출력은 …/work/project/marker.txt 한 줄이었다. CDPATH=;는 $(...) 안에서 실행되므로 호출한 셸의 검색 설정을 바꾸지 않는다. unset CDPATH를 그 자리에 넣은 비교도 같은 결과였다. 디렉터리 이동 역시 명령 치환 안에서만 일어났다.
대상이 현재 디렉터리 바로 아래임을 코드에 드러내려면 destination=$(cd -- ./project && pwd -P)로 바꿀 수도 있다. 이 경우에는 CDPATH를 비우지 않아도 ./project가 현재 위치를 가리켰다. 같은 두 디렉터리로 cd만의 출력과 실제 이동 위치를 따로 측정한 결과는 다음과 같았다. 네 경우 모두 이동 상태는 0이었다.
CDPATH없음,cd project: 출력 없음,work/project로 이동.CDPATH없음,cd ./project: 출력 없음,work/project로 이동.CDPATH가lookup,cd project:lookup/project의 절대경로 한 줄 출력, 그곳으로 이동.CDPATH가lookup,cd ./project: 출력 없음,work/project로 이동.
목적지가 없을 때도 확인했다. cd -- ./missing && pwd -P는 상태 1과 디렉터리가 없다는 표준오류를 남겼고, 변수 값은 비어 있었다. && 덕분에 이동 실패 뒤의 pwd는 실행되지 않았다. 자기 스크립트에서도 실패하면 후속 경로를 사용하지 말고 디렉터리 이름과 접근 권한부터 확인한다. cd와 pwd를 세미콜론으로 연결하면 이동에 실패한 뒤 원래 위치를 출력할 수 있으므로 위 코드처럼 성공 여부를 연결한다.
출력만 지울지, 이동 대상도 바꿀지 구분한다
destination=$(cd -- project >/dev/null && pwd -P)도 두 줄 출력을 없앴다. 다만 실제 결과는 lookup/project였다. 리다이렉션은 cd의 표준출력만 숨기며 검색 결과는 바꾸지 않는다. 검색된 디렉터리가 원래 목적지인 경우에는 이 방법을 쓸 수 있다. 현재 위치의 project가 목적지라면 CDPATH를 비우거나 ./project로 지정해야 한다.
명령 치환 문서 (새 탭에서 열림)에 따르면 $(...)는 표준출력을 받아 끝의 개행을 제거한다. 두 경로 사이의 개행은 끝에 있지 않아 남는다. 끝 개행을 다시 붙이거나 출력의 마지막 줄만 고르는 것으로는 잘못 선택된 디렉터리까지 바로잡을 수 없다.
직접 실행한 환경은 WSL2의 Ubuntu-24.04 배포판, Bash 5.2.21이며 프로필을 읽지 않은 새 Bash와 합성 디렉터리를 사용했다. 링크한 GNU Bash 매뉴얼은 유지관리자가 제공하는 5.3판이다. 관찰은 Bash 내장 cd·pwd와 일반 디렉터리에 한정하며, 다른 셸이나 이 명령들을 감싼 사용자 함수는 실행하지 않았다. 위 조건을 정리해도 추가 출력이 남는다면 해당 함수나 명령 치환 안의 다른 표준출력도 확인해야 한다.