Featured image of post [Bash Shell] 06. mkdir, rmdir - 디렉터리 생성과 삭제

[Bash Shell] 06. mkdir, rmdir - 디렉터리 생성과 삭제

리눅스·유닉스에서 디렉터리를 만드는 mkdir과 빈 디렉터리만 지우는 rmdir을 다룹니다. -p 옵션의 중첩 생성·멱등성, -m 권한 지정, umask 영향, rmdir이 비어있지 않으면 반드시 실패하는 안전장치까지 예제로 정리합니다.

mkdir은 지정한 경로에 디렉터리를 만들고, rmdir비어 있는 디렉터리만 골라 제거하는 명령어다. 두 명령은 대칭적으로 보이지만 실제로는 비대칭적으로 설계돼 있다 — mkdir -p는 중간 경로까지 알아서 만들어 주는 반면, rmdir은 안에 무언가 하나라도 남아 있으면 무조건 실패한다.

이 장을 읽기 전에

선행 챕터: 이 장은 05장: touch에서 빈 파일을 만드는 법을 다룬 뒤 이어진다. 파일을 만드는 법을 알았으니, 이제 그 파일들을 담을 디렉터리를 만들고 지우는 법으로 넘어가는 자연스러운 흐름이다. mkdir·rmdir 자체는 01장: cd, pwd에서 다룬 경로 이동 개념 정도만 있으면 충분하다.

이 장의 깊이: 입문 난이도다. 디렉터리를 만들고 지우는 기본 옵션과 실무에서 자주 쓰는 조합을 다룬다. 다루지 않는 것: 비어 있지 않은 디렉터리를 통째로 삭제하는 재귀 삭제(rm -r)는 이 장의 범위가 아니다 — 그 이유와 방법은 07장: cp, mv, rm에서 다룬다. 권한 표기(755, 700 같은 8진수 모드)의 상세한 의미와 chmod로 기존 파일의 권한을 바꾸는 법은 36장: chmod, chown에서 다룬다.

당신의 수준에 맞는 경로

수준읽을 부분핵심 목표
디렉터리를 빨리 만들고 지워야 하는 사람“사용법·옵션”~“예시”mkdir -p로 중첩 경로를 한 번에 만들고 rmdir로 빈 디렉터리를 정리한다
스크립트에 넣을 안전한 디렉터리 생성 로직이 필요한 사람“예시"부터 “흔한 오개념"까지 전체mkdir -p의 멱등성과 rmdir의 안전장치를 이해하고, umask가 만들어지는 디렉터리의 기본 권한에 어떻게 관여하는지 설명할 수 있다

개요 + 정신 모델

mkdirrmdir은 짝을 이루는 명령어처럼 보이지만, 둘이 “허용하는 범위"는 서로 다르게 설계돼 있다. mkdir -p는 목적지 경로에 이르는 중간 디렉터리가 없으면 군말 없이 다 만들어 준다mkdir -p a/b/c를 실행했을 때 aa/b도 없다면 셋 다 순서대로 생성한다. 반대로 rmdir은 “정말 비어 있는 디렉터리만” 지우도록 만들어졌고, 그 조건이 깨지면(파일이든 하위 디렉터리든 하나라도 남아 있으면) 아예 아무것도 지우지 않고 실패한다. 즉 생성은 관대하게, 삭제는 보수적으로라는 비대칭적 원칙이 두 명령어를 관통한다. 이 비대칭은 우연이 아니다 — 디렉터리를 만드는 실수는 되돌리기 쉽지만(다시 지우면 그만), 안에 내용물이 든 디렉터리를 실수로 지우는 것은 되돌릴 수 없는 데이터 손실이기 때문이다. rmdir은 그 위험을 원천적으로 차단하도록 설계됐고, 진짜 재귀 삭제가 필요한 순간에는 rm -r이라는 별도의, 더 명시적으로 위험한 명령을 쓰도록 셸 생태계 전체가 유도한다.

사용법·옵션

1
2
mkdir [옵션] 디렉터리...
rmdir [옵션] 디렉터리...

두 명령 모두 인자로 디렉터리 경로를 하나 이상 받으며, 여러 개를 한 번에 지정하면 순서대로 처리한다.

mkdir 옵션

옵션설명
-p, --parents상위 경로가 없으면 함께 생성한다. 대상 디렉터리가 이미 존재해도 에러 없이 조용히 성공한다
-m MODE, --mode=MODE생성할 디렉터리의 권한을 MODE(8진수)로 지정한다. 지정하지 않으면 777에서 현재 umask를 뺀 값이 적용된다
-v, --verbose디렉터리를 만들 때마다 메시지를 출력한다

rmdir 옵션

옵션설명
-p, --parents지정한 경로와 그 상위 경로를 순서대로 제거한다. 상위 디렉터리 중 하나라도 비어 있지 않으면 그 지점에서 멈춘다
--ignore-fail-on-non-empty디렉터리가 비어 있지 않아 실패해도 에러를 무시하고 다음 인자로 넘어간다
-v, --verbose디렉터리를 지울 때마다 메시지를 출력한다

예시

중첩 디렉터리 한 번에 생성

1
2
# a, a/b, a/b/c를 순서대로 만든다. 중간에 a나 a/b가 없어도 에러 없이 모두 생성한다
mkdir -p a/b/c

권한을 지정해 생성

1
2
# 소유자만 읽기/쓰기/실행 가능한 디렉터리를 생성한다(비밀 설정 파일 저장용 등)
mkdir -m 700 private_dir

여러 디렉터리 한 번에 생성

1
2
3
4
5
# src, test, docs 세 디렉터리를 한 번에 만든다
mkdir src test docs

# 여러 프로젝트 하위 구조를 한 번에 만든다
mkdir -p project/{src,test,docs}

빈 디렉터리 삭제

1
2
# empty_dir이 비어 있으면 삭제, 파일이나 하위 디렉터리가 남아 있으면 에러 후 삭제하지 않는다
rmdir empty_dir

여러 디렉터리를 한 번에 삭제

1
2
# a/b/c, a/b, a를 순서대로 지운다. 각 단계에서 비어 있지 않으면 그 지점에서 멈춘다
rmdir -p a/b/c

스크립트에서 멱등하게 디렉터리 준비

1
2
# 이미 있어도 에러 없이 넘어가므로, 스크립트를 여러 번 실행해도 안전하다
mkdir -p /var/log/myapp

주의사항·함정

rmdir은 비어 있지 않으면 반드시 실패한다 — 이것은 버그가 아니라 안전장치다. rmdir은 대상 디렉터리 안에 파일이든 하위 디렉터리든(숨김 파일 포함) 하나라도 남아 있으면 rmdir: failed to remove 'dir': Directory not empty라는 메시지와 함께 아무것도 지우지 않고 그대로 실패한다. 이 “전부 아니면 전무” 동작 덕분에 rmdir을 스크립트에 넣어도 실수로 내용물이 들어 있는 디렉터리가 통째로 사라지는 사고는 일어나지 않는다. 이 점에서 rmdir07장에서 다룰 rm -r과 정반대다 — rm -r은 내용물이 있어도 (확인 없이) 재귀적으로 지워 버리므로, “정말 비어 있는지 확인하고 지우고 싶다"는 의도가 있다면 rm -r 대신 rmdir을 쓰는 것 자체가 하나의 안전장치가 된다.

mkdir -p는 이미 있는 디렉터리에도 에러 없이 조용히 성공한다 — 스크립트 멱등성의 관용구다. -p 없이 mkdir dir을 실행했는데 dir이 이미 존재하면 mkdir: cannot create directory 'dir': File exists로 실패한다. 반면 mkdir -p dir은 대상이 이미 디렉터리로 존재하면 아무 일도 하지 않고 종료 코드 0을 반환한다(단, 같은 이름의 파일이 이미 있으면 이때는 -p를 써도 실패한다). 이 성질 때문에 배포·설치 스크립트에서 “이 디렉터리가 없으면 만들고, 있으면 그대로 둔다"는 로직을 조건문 없이 mkdir -p target_dir 한 줄로 표현하는 것이 표준 관용구로 자리 잡았다. 스크립트를 몇 번을 다시 실행해도 같은 상태로 수렴한다는 의미에서 이를 멱등성(idempotency)이라 부른다.

umaskmkdir로 만든 디렉터리의 기본 권한을 결정한다. -m으로 모드를 명시하지 않고 mkdir을 실행하면, 생성되는 디렉터리의 권한은 디렉터리 최대 권한인 777에서 현재 셸의 umask 값을 뺀 값이 된다. 예를 들어 umask022(대부분의 리눅스 배포판 기본값)라면 mkdir newdir로 만든 디렉터리는 755(소유자 rwx, 그룹·기타 r-x) 권한을 갖는다. umask는 셸 세션 전체에 적용되는 전역 설정이라, 같은 mkdir 명령이라도 실행하는 셸의 umask 값에 따라 결과 권한이 달라질 수 있다는 점을 스크립트 작성 시 염두에 둬야 한다 — 특정 권한을 반드시 보장해야 한다면 umask에 기대지 말고 -m으로 명시하는 편이 안전하다.

흔한 오개념

"rmdir -prm -r처럼 디렉터리 안의 내용물까지 재귀적으로 지워 준다”는 흔한 오해다. rmdir -p a/b/c-p는 “재귀 삭제"가 아니라 “지정한 경로와 그 상위 경로를 순서대로 지운다"는 뜻이다. 즉 a/b/c, a/b, a 세 디렉터리 각각이 비어 있어야 순서대로 지워지며, 그중 하나라도(예: a 아래에 a/b와 무관한 다른 파일이 있는 경우) 비어 있지 않으면 그 지점에서 멈추고 나머지는 그대로 남는다. 내용물이 있는 디렉터리를 하위까지 통째로 지우려면 애초에 rmdir이 아니라 rm -r을 써야 한다.

다음 장에서는

디렉터리는 만들고 지울 수 있게 됐으니, 이제 그 안의 내용물을 옮기고 지우는 법으로 넘어간다. 07장: cp, mv, rm에서는 파일과 디렉터리를 복사·이동하고, rmdir이 거부하는 “비어 있지 않은 디렉터리 삭제"를 rm -r로 어떻게 다루는지 다룬다.

평가 기준

  • mkdir -p가 중간 경로를 재귀적으로 생성하는 것과, rmdir이 반드시 빈 디렉터리만 지우는 것 사이의 비대칭을 설명할 수 있다.
  • -m 옵션으로 디렉터리 생성 시 권한을 직접 지정하고, 지정하지 않았을 때 umask가 결과 권한에 어떻게 관여하는지 설명할 수 있다.
  • mkdir -p가 이미 존재하는 디렉터리에 대해 에러 없이 성공하는 멱등성을 스크립트에서 활용할 수 있다.
  • rmdir -p가 재귀 삭제가 아니라 상위 경로까지의 순차 삭제라는 점을 구분할 수 있다.

참고