Devin.KR
로그인

리눅스 dirname 명령어 사용법 - 경로에서 디렉터리만 뽑아 스크립트 기준점 잡기

개발자 조회 1

이 명령어를 언제 쓰는가

파일 경로를 받아 "그 파일이 들어갈 디렉터리"를 알아야 할 때 쓴다. 출력 파일을 만들기 전에 상위 디렉터리를 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 -pcd에 넘기면 엉뚱한 디렉터리를 만들거나 이동한다. 입력이 항상 절대경로라는 보장이 없으면 dirname을 쓰는 편이 안전하다.

dirname은 파일 존재 여부를 검사하지 않는다. 오타가 난 경로를 줘도 조용히 문자열을 잘라 결과를 낸다. 결과를 그대로 rm -rf "$(dirname "$X")" 같은 곳에 넣으면 사고가 난다. 특히 $X가 비어 있으면 dirname은 .을 돌려주므로, 현재 디렉터리를 지우는 코드가 된다. 삭제·이동 계열에 넘길 값은 반드시 비어 있지 않은지, 예상 접두사로 시작하는지 확인하라.

끝 슬래시 유무로 결과가 한 단계 달라진다. dirname /var/log/var지만 dirname /var/log//var다. 사용자 입력을 그대로 받는다면 디렉터리를 의도한 것인지 파일을 의도한 것인지 스크립트가 알 수 없다. 입력을 realpath -m으로 한 번 정규화한 뒤 다루면 이런 흔들림이 줄어든다.

함께 보면 좋은 명령어

  • basename — 반대쪽인 파일명 부분을 뽑는다. dirname과 거의 항상 함께 쓴다.
  • realpath / readlink — 상대경로와 심볼릭 링크를 걷어낸 뒤 dirname에 넘기면 결과가 안정적이다.
  • mkdirmkdir -p "$(dirname "$OUT")" 조합이 사실상 관용구다.