cd: 셸의 현재 작업 디렉터리를 바꾸는 내장 명령
cd(change directory)는 셸 프로세스의 현재 작업 디렉터리(CWD)를 변경하는 셸 내장 명령이다. 외부 프로그램이 아니라 셸 자신의 상태를 바꾸기 때문에 내장 명령으로 구현된다. 절대 경로와 상대 경로, `~`, `-`, `..` 같은 표기를 이해하면 터미널 이동이 훨씬 빨라진다.
By 송민성
1. 개념
cd(change directory)는 셸의 현재 작업 디렉터리(CWD, Current Working Directory) 를 바꾸는 명령이다. 상대 경로를 해석할 때 기준이 되는 위치가 CWD다.
pwd # 현재 위치 출력
cd /var/log # 절대 경로로 이동
pwd경로는 두 가지로 나뉜다.
| 구분 | 설명 | 예 |
|---|---|---|
| 절대 경로(absolute path) | 루트 /부터 시작 | /etc/nginx |
| 상대 경로(relative path) | CWD 기준 | ../logs, src/app |
자주 쓰는 특수 표기는 다음과 같다.
| 표기 | 의미 |
|---|---|
| . | 현재 디렉터리 |
| .. | 부모 디렉터리 |
| ~ | 현재 사용자의 홈 디렉터리 |
| - | 직전 디렉터리 ($OLDPWD) |
| 인자 없음 | 홈 디렉터리로 이동 |
2. 왜 사용하는가
- 파일 경로를 매번 길게 쓰지 않고, 작업 위치를 기준으로 짧은 상대 경로를 쓸 수 있다.
git,npm,make같은 도구는 대개 CWD를 기준으로 동작한다. 프로젝트 루트로 이동한 뒤 실행하는 것이 기본 흐름이다.- 스크립트에서 작업 기준 위치를 명확히 지정할 수 있다.
3. 동작 원리
모든 프로세스는 자신만의 CWD를 가진다. 셸도 하나의 프로세스이며, cd는 내부적으로 chdir() 시스템 콜을 호출해 셸 프로세스의 CWD를 바꾼다.
왜 `cd`는 내장 명령(builtin)인가? 외부 프로그램(/bin/ls 같은 실행 파일)을 실행하면 셸은 fork()로 자식 프로세스를 만들고 그 안에서 프로그램을 실행한다. 자식 프로세스가 CWD를 바꿔도 부모(셸)의 CWD는 바뀌지 않는다. 그래서 cd가 외부 프로그램이라면 아무 효과가 없다. 셸 자신이 직접 chdir()를 호출해야 하므로 내장 명령이다.
type cd # cd is a shell builtincd는 이동 후 환경 변수도 갱신한다.
PWD: 새 현재 디렉터리OLDPWD: 이동 전 디렉터리 (cd -가 사용)
또한 심볼릭 링크(symbolic link)를 따라 이동할 때, 기본 동작(-L)은 링크 경로 그대로 PWD에 기록하고, -P 옵션은 링크를 풀어 실제 물리 경로를 기록한다.
4. 코드 예제
#!/usr/bin/env bash
set -e
# 임시 디렉터리 구조 만들기
base="$(mktemp -d)"
mkdir -p "$base/project/src" "$base/project/logs"
cd "$base/project" # 절대 경로 이동
pwd
cd src # 상대 경로 이동
pwd
cd ../logs # 부모로 올라간 뒤 logs로
pwd
cd - # 직전 디렉터리(src)로 복귀
cd # 홈으로 이동
pwd
# 공백이 있는 경로는 따옴표로 감싼다
mkdir -p "$base/my docs"
cd "$base/my docs"
pwd
# 서브셸에서 이동하면 바깥 셸의 CWD는 유지된다
cd "$base"
( cd project/src && pwd )
pwd
# 심볼릭 링크: 논리 경로(-L) vs 물리 경로(-P)
ln -s "$base/project" "$base/link"
cd -L "$base/link" && pwd
cd -P "$base/link" && pwd
rm -rf "$base"실행하면 서브셸 ( ... ) 안에서의 cd가 바깥 셸에 영향을 주지 않는 것을 확인할 수 있다. 서브셸도 별도 프로세스이기 때문이다.
5. 시간 복잡도 또는 성능 특성
cd는 경로를 구성하는 각 요소(컴포넌트)를 차례로 탐색(path lookup)하므로 비용은 대략 경로 깊이에 비례한다. 다만 커널의 디렉터리 엔트리 캐시(dentry cache) 덕분에 실사용에서는 체감할 수 없는 수준이다. 별도로 외우거나 최적화할 성능 수치는 없다.
6. 실무 사용 사례
- 프로젝트 이동:
cd ~/work/my-app && npm run dev - 로그 확인:
cd /var/log && tail -f syslog(환경에 따라 로그 파일 이름은 다를 수 있다) - 스크립트에서 기준 위치 고정: 스크립트가 어느 위치에서 호출되든 자기 디렉터리를 기준으로 동작하게 한다.
#!/usr/bin/env bash
cd "$(dirname "$0")" || exit 1
pwd- 자주 가는 곳 단축:
CDPATH환경 변수에 탐색 기준 디렉터리를 등록하면, 어느 위치에서든cd my-app처럼 짧게 이동할 수 있다.
export CDPATH=".:$HOME/work"
cd my-app # ./my-app 이 없으면 ~/work/my-app 을 찾는다- 임시 이동:
pushd/popd는 디렉터리 스택(stack)으로 이동 이력을 관리한다.cd -는 직전 한 곳만 기억하지만pushd는 여러 곳을 쌓을 수 있다. (bash, zsh 등에서 지원)
7. 주의할 점
- 실패 처리:
cd가 실패했는데도 다음 명령이 계속 실행되면 엉뚱한 위치에서 작업하게 된다. 특히rm과 조합하면 위험하다.
# 위험: cd 실패 시 현재 위치에서 삭제가 실행된다
cd build; rm -rf ./*
# 안전: 성공했을 때만 실행
cd build && rm -rf ./*- 공백 포함 경로: 변수를 쓸 때는
cd "$dir"처럼 따옴표로 감싼다. - 권한: 디렉터리에 실행(x) 권한이 없으면 진입할 수 없다(
Permission denied). - `cd`는 셸 상태를 바꾼다: 스크립트 안의
cd는 스크립트를 실행한 별도 프로세스에만 영향을 준다. 스크립트를 실행한 뒤 터미널의 위치가 그대로인 것은 정상이다. 현재 셸에서 이동시키려면source script.sh로 실행해야 한다. - `cd ..`와 심볼릭 링크: 링크를 통해 들어온 경우
-L과-P에 따라..의 결과가 다를 수 있다.
8. 핵심 정리
cd는 셸 프로세스의 CWD를chdir()시스템 콜로 바꾸는 셸 내장 명령이다.- 자식 프로세스는 부모의 CWD를 바꿀 수 없으므로 외부 프로그램으로는 구현할 수 없다.
~(홈),-(직전 위치),..(부모), 인자 없음(홈)을 익히면 이동이 빨라진다.- 스크립트에서는
cd dir && 명령또는cd dir || exit 1로 실패를 반드시 처리한다. - 경로에 공백이 있을 수 있으므로 변수는
"$dir"처럼 따옴표로 감싼다.