Devin.KR
로그인

리눅스 realpath 명령어 사용법 - 절대경로 정규화와 스크립트 기준 디렉터리 잡기

개발자 조회 1

이 명령어를 언제 쓰는가

셸 스크립트가 "어디서 실행되든 똑같이 동작"하게 만들 때 쓴다. 스크립트 안에서 ./config/app.conf 같은 상대경로를 쓰면 호출한 사람의 현재 디렉터리에 따라 결과가 달라진다. realpath로 한 번 절대경로로 고정해 두면 이 문제가 사라진다.

운영에서는 심볼릭 링크를 걷어낼 때 더 자주 쓴다. /opt/app/current가 실제로 어느 릴리스 디렉터리를 가리키는지, /var/log가 별도 볼륨의 어디로 연결돼 있는지 확인해야 배포 사고를 막을 수 있다. ..//, 끝의 슬래시까지 전부 정리해 주는 것도 장점이다.

기본 형식

realpath [옵션] 경로...

경로를 여러 개 주면 한 줄에 하나씩 결과를 낸다. 기본 동작은 마지막 요소를 뺀 나머지가 전부 존재해야 하고, 심볼릭 링크는 모두 따라간다는 것이다(GNU man 페이지의 all but the last component must exist). 즉 realpath ./out/new.log./out만 있으면 성공하지만, 중간 디렉터리가 없으면 종료 코드 1과 함께 에러를 낸다.

자주 쓰는 옵션

옵션의미예시
-e마지막 요소까지 전부 존재해야 한다. 기본값보다 엄격realpath -e ./conf
-m아무것도 존재하지 않아도 된다. 만들 파일의 경로 계산용realpath -m ./out/new.log
-s심볼릭 링크를 따라가지 않고 문자열만 정규화realpath -s /opt/app/current
--relative-to=DD 기준의 상대경로로 출력realpath --relative-to=/opt /opt/app/bin
-q에러 메시지를 숨긴다(종료 코드로만 판단)realpath -q "$p"
-z줄바꿈 대신 NUL로 구분. xargs -0와 짝realpath -z *

실전 예제

1) 스크립트가 자기 위치를 기준으로 파일을 찾게 한다. 크론이나 systemd에서 실행될 때 현재 디렉터리가 /여도 안전하다.

#!/bin/bash
set -euo pipefail
SCRIPT="$(realpath "$0")"
BASE="$(dirname "$SCRIPT")"
source "$BASE/lib/common.sh"

2) 배포 심볼릭 링크가 실제 어느 릴리스를 보는지 확인한다. 롤백 전에 반드시 하는 확인이다.

realpath /opt/app/current
/opt/app/releases/2026-08-25T1130

3) 아직 만들지 않은 출력 디렉터리·파일의 절대경로를 계산한다. 파일 이름만 없는 경우는 기본 동작으로도 되지만, out 디렉터리 자체가 없을 수 있으므로 -m이 안전하다.

OUT="$(realpath -m "${1:-./out}/report-$(date +%F).csv")"
mkdir -p "$(dirname "$OUT")"

4) 사용자 입력이 허용된 디렉터리 밖으로 나가지 않는지 검사한다. ../../etc/passwd 같은 경로 탈출을 막는 기본 패턴이다.

ROOT=/srv/uploads
TARGET="$(realpath -m "$ROOT/$USER_INPUT")"
case "$TARGET" in
  "$ROOT"/*) echo "ok: $TARGET" ;;
  *) echo "경로 탈출 시도" >&2; exit 1 ;;
esac

5) 절대경로를 특정 기준의 상대경로로 바꾼다. tar나 rsync 인자를 만들 때 편하다.

realpath --relative-to=/opt/app /opt/app/logs/2026/08
logs/2026/08

함정과 주의점

"어디까지 존재해야 하는가"가 옵션마다 다르다. 기본값은 마지막 요소만 없어도 되고, -e는 전부 있어야 하며, -m은 하나도 없어도 된다. 아직 만들지 않은 디렉터리 아래 경로를 기본값으로 계산하면 No such file or directory로 실패하고, set -e가 걸려 있으면 그 자리에서 스크립트가 종료된다. 반대로 반드시 있어야 하는 입력을 기본값으로 검사하면 오타 난 파일명이 통과해 버린다. 만들 대상이면 -m, 있어야 하는 입력이면 -e의도를 명시하라.

macOS의 realpath는 GNU와 다르다. 이 글의 -m, -s, --relative-to는 GNU coreutils 기능이다. macOS에 기본 탑재된 realpath는 사실상 -q 정도만 받으며, 옵션을 주면 illegal option으로 실패한다. 맥에서 개발한 스크립트를 서버에 올릴 때 흔히 터진다. 맥에서는 brew install coreutilsgrealpath를 쓰거나, 이식성이 필요하면 cd "$(dirname "$0")" && pwd -P로 대체한다.

아주 오래된 서버에는 realpath가 아예 없다. realpath가 coreutils에 들어온 것은 8.15(2012)부터라, CentOS 6 계열 등에는 없거나 별도 패키지다. 그런 환경에서는 readlink -f가 사실상 같은 일을 한다. 반대로 최신 환경만 다룬다면 의도가 분명한 realpath 쪽이 읽기 좋다.

-s는 링크를 따라가지 않는다. /opt/app/current/bin-s로 정규화하면 링크가 그대로 남은 채 ..만 정리된다. 실제 파일 위치를 알아야 하는 상황에서 -s를 쓰면 엉뚱한 경로를 얻는다.

함께 보면 좋은 명령어

  • readlinkreadlink -f는 realpath의 사실상 동의어이며 구형 서버에서 대체제가 된다.
  • dirname / basename — realpath로 고정한 절대경로를 디렉터리와 파일명으로 쪼갤 때 짝으로 쓴다.
  • pwdpwd -P는 현재 디렉터리의 심볼릭 링크를 걷어낸 실제 경로를 준다.