리눅스 dirname 명령어 사용법 - 경로에서 디렉터리만 뽑아 스크립트 기준점 잡기
이 명령어를 언제 쓰는가
파일 경로를 받아 "그 파일이 들어갈 디렉터리"를 알아야 할 때 쓴다. 출력 파일을 만들기 전에 상위 디렉터리를 mkdir -p로 미리 만드는 코드가 대표적이다. 사용자가 /data/out/2026/08/report.csv를 지정했다면 /data/out/2026/08이 있어야 쓰기가 성공한다.
스크립트가 자기 자신이 놓인 디렉터리를 기준점으로 삼을 때도 필수다. 크론이나 systemd에서 실행되면 현재 디렉터리가 /거나 예상 밖의 위치라, 상대경로로 짠 스크립트는 거기서 무너진다.
기본 형식
dirname 경로...
경로에서 마지막 /와 그 뒤를 떼고 앞부분을 출력한다. 끝의 슬래시는 먼저 무시한다. 실제 파일이 존재하는지는 전혀 확인하지 않으며, 순수하게 문자열만 다룬다는 점이 중요하다.
자주 쓰는 옵션
| 옵션 | 의미 | 예시 |
|---|---|---|
| (없음) | 인자를 여러 개 주면 한 줄에 하나씩 출력 | dirname /a/b.txt /c/d.txt |
| -z | 줄바꿈 대신 NUL 구분(GNU 전용) | dirname -z /a/b.txt |
옵션이라 할 게 사실상 없다. 동작 규칙을 정확히 아는 것이 옵션을 외우는 것보다 중요하다.
| 입력 | 출력 | 이유 |
|---|---|---|
| /var/log/app.log | /var/log | 일반적인 경우 |
| app.log | . | 슬래시가 없으면 현재 디렉터리 |
| /var/log/ | /var | 끝 슬래시를 먼저 버리고 log를 뗀다 |
| /var | / | 상위가 루트 |
| / | / | 루트의 상위는 루트 |
실전 예제
1) 출력 파일을 쓰기 전에 상위 디렉터리를 보장한다. 이 두 줄이 없어서 나는 "No such file or directory"가 정말 많다.
OUT=/data/out/$(date +%Y/%m)/report.csv
mkdir -p "$(dirname "$OUT")"
: > "$OUT"
2) 스크립트 자기 디렉터리를 기준으로 설정 파일을 읽는다. 어디서 호출되든 동작한다.
#!/bin/bash
set -euo pipefail
BASE="$(cd "$(dirname "$0")" && pwd -P)"
source "$BASE/config.env"
3) 심볼릭 링크로 호출돼도 실제 위치를 잡는다. /usr/local/bin에 링크를 걸어 쓰는 스크립트에 필요하다.
SELF="$(readlink -f "$0")"
BASE="$(dirname "$SELF")"
4) 특정 파일이 들어 있는 디렉터리 목록을 뽑는다. 어떤 서비스 디렉터리에 설정 파일이 흩어져 있는지 확인할 때 쓴다.
find /etc -name 'ssl.conf' -print0 | xargs -0 -n1 dirname | sort -u
5) 셸 내장 기능으로 대체한다. 다만 아래 함정 항목을 반드시 같이 보라.
p=/var/log/nginx/access.log
echo "${p%/*}" # /var/log/nginx
함정과 주의점
파라미터 확장 ${p%/*}는 dirname과 동치가 아니다. 슬래시가 없는 access.log를 넣으면 dirname은 .을 주지만 ${p%/*}는 access.log를 그대로 돌려준다. 이 값을 mkdir -p나 cd에 넘기면 엉뚱한 디렉터리를 만들거나 이동한다. 입력이 항상 절대경로라는 보장이 없으면 dirname을 쓰는 편이 안전하다.
dirname은 파일 존재 여부를 검사하지 않는다. 오타가 난 경로를 줘도 조용히 문자열을 잘라 결과를 낸다. 결과를 그대로 rm -rf "$(dirname "$X")" 같은 곳에 넣으면 사고가 난다. 특히 $X가 비어 있으면 dirname은 .을 돌려주므로, 현재 디렉터리를 지우는 코드가 된다. 삭제·이동 계열에 넘길 값은 반드시 비어 있지 않은지, 예상 접두사로 시작하는지 확인하라.
끝 슬래시 유무로 결과가 한 단계 달라진다. dirname /var/log는 /var지만 dirname /var/log/도 /var다. 사용자 입력을 그대로 받는다면 디렉터리를 의도한 것인지 파일을 의도한 것인지 스크립트가 알 수 없다. 입력을 realpath -m으로 한 번 정규화한 뒤 다루면 이런 흔들림이 줄어든다.
함께 보면 좋은 명령어
- basename — 반대쪽인 파일명 부분을 뽑는다. dirname과 거의 항상 함께 쓴다.
- realpath / readlink — 상대경로와 심볼릭 링크를 걷어낸 뒤 dirname에 넘기면 결과가 안정적이다.
- mkdir —
mkdir -p "$(dirname "$OUT")"조합이 사실상 관용구다.