우분투 실전 명령어 | basename dirname으로 경로 문자열 안전하게 다루기

우분투 실전 명령어 | basename dirname으로 경로 문자열 안전하게 다루기

쉘 스크립트에서 파일명을 잘라 쓰거나 상위 디렉터리를 뽑아야 할 때가 자주 있습니다. 이때 cut이나 sed로 억지 파싱을 하면 공백, 확장자, 슬래시 유무에서 쉽게 깨집니다. basename과 dirname을 쓰면 경로 처리 실수를 크게 줄일 수 있습니다.

언제 쓰는가

  • 업로드 파일 경로에서 파일명만 로그에 남길 때
  • 백업 스크립트에서 상위 디렉터리 기준으로 대상 폴더를 만들 때
  • 확장자를 제거해 결과 파일명을 만들 때

바로 쓰는 명령어

# 파일명만 추출
basename /var/log/nginx/access.log

# 디렉터리 경로만 추출
dirname /var/log/nginx/access.log

# 확장자 .log 제거 후 베이스 이름 추출
basename /var/log/nginx/access.log .log
# 변수와 함께 안전하게 사용
src="/data/releases/app-v2.3.1.tar.gz"
name=$(basename "$src")
parent=$(dirname "$src")

echo "name=$name"
echo "parent=$parent"

핵심 옵션/패턴

  • basename PATH: 마지막 경로 요소만 반환
  • basename PATH SUFFIX: 끝이 SUFFIX와 일치하면 제거
  • dirname PATH: 마지막 요소를 제외한 디렉터리 경로 반환
  • 항상 따옴표로 감싸기: "$var" 형태를 습관화하면 공백이 있는 경로도 안전
# 여러 파일을 처리할 때 패턴
while IFS= read -r p; do
  echo "file=$(basename \"$p\") dir=$(dirname \"$p\")"
done < paths.txt

명령 출력 예시

$ basename /opt/app/config.yaml
config.yaml

$ dirname /opt/app/config.yaml
/opt/app

$ basename /opt/app/config.yaml .yaml
config

자주 하는 실수

  • 실수 1: 경로 변수를 따옴표 없이 사용해서 공백 포함 경로에서 분해됨
  • 실수 2: 확장자 제거를 ${name%.*}만으로 처리하다가 다중 확장자에서 의도와 다르게 잘림
  • 실수 3: 경로 끝 슬래시를 고려하지 않아 결과가 기대와 다름

검증 방법

# 케이스별로 결과 점검
for p in \
  "/tmp/a.txt" \
  "/tmp/my file.txt" \
  "/tmp/archive.tar.gz" \
  "/tmp/dir/"; do
  printf "path=%s\n" "$p"
  printf "  basename=%s\n" "$(basename "$p")"
  printf "  dirname =%s\n" "$(dirname "$p")"
done
# 스크립트 문법/안전성 기본 점검
bash -n your_script.sh
shellcheck your_script.sh

운영 팁

  • 경로 처리는 문자열 파싱보다 전용 도구를 우선 사용하면 유지보수가 쉬워집니다.
  • 사용자 입력 경로를 받을 때는 normalize 단계와 존재 여부 확인을 분리하세요.
  • 배치 스크립트에서는 basename/dirname 결과를 로그에 남겨 장애 분석 시간을 줄이세요.

출처

  • GNU Coreutils
  • Ubuntu Manpages