우분투 실전 명령어 | 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