리눅스 cp 명령어 사용법 - 디렉토리 복사와 -a 옵션 실전 예제
이 명령어를 언제 쓰는가
cp는 파일과 디렉토리를 복사한다. 실무에서 가장 많이 쓰는 순간은 설정 파일을 고치기 직전의 백업이다. cp nginx.conf nginx.conf.20260825 한 줄이 롤백 시간을 몇 시간 단축한다.
그다음이 배포·이관이다. 다만 서버 간 복사나 큰 디렉토리 동기화는 cp보다 rsync가 맞다. cp는 중단되면 처음부터 다시 해야 하고 진행률도 안 보인다. cp는 같은 서버 안의 소규모 복사, rsync는 그 밖의 경우로 나눠 쓴다.
기본 형식
cp [옵션] 원본 [원본 ...] 대상
원본이 여러 개면 대상은 반드시 디렉토리여야 한다. 대상이 이미 있는 파일이면 경고 없이 덮어쓴다.
자주 쓰는 옵션
| 옵션 | 의미 | 예시 |
|---|---|---|
| -r (-R) | 디렉토리를 재귀적으로 복사 | cp -r conf.d /backup/ |
| -a | 보존 복사(-dR --preserve=all). 권한·소유자·시각·링크 유지 | cp -a /opt/app /opt/app.bak |
| -p | 권한·소유자·타임스탬프 보존 | cp -p my.cnf my.cnf.bak |
| -i | 덮어쓰기 전에 확인 | cp -i a.conf /etc/ |
| -n | 대상이 있으면 덮어쓰지 않고 건너뛴다 | cp -n *.conf /etc/app/ |
| -u | 원본이 더 새로울 때만 복사 | cp -u -r src/ dst/ |
| -v | 복사한 파일을 출력 | cp -av a b |
| --backup=numbered | 덮어쓸 때 기존 파일을 번호 붙여 남긴다(GNU) | cp --backup=numbered new.conf /etc/app.conf |
실전 예제
1) 설정 파일을 고치기 전 날짜 붙여 백업 — 원본 시각과 권한을 그대로 남겨야 나중에 비교가 된다.
cp -p /etc/nginx/nginx.conf /etc/nginx/nginx.conf.$(date +%Y%m%d)
2) 애플리케이션 디렉토리 통째 백업 — 소유자와 퍼미션이 어긋나면 서비스가 안 뜨므로 -a를 쓴다.
cp -a /opt/app /opt/app.bak.20260825
3) 숨김 파일까지 포함해 디렉토리 내용만 옮기기 — src/*는 .env 같은 점 파일을 빼먹는다. src/.로 쓴다.
cp -a /opt/app/src/. /opt/app/new/
4) 여러 파일을 한 디렉토리로 모으기 — 마지막 인자가 대상이라는 규칙만 기억하면 된다.
cp -v app.conf db.conf log.conf /etc/myapp/
5) 이미 있는 파일은 건드리지 않고 새 파일만 채우기 — 기본 설정 배포처럼 기존 운영 설정을 지키고 싶을 때.
cp -n -r defaults/. /etc/myapp/
6) 원본과 사본이 같은지 확인 — 큰 파일을 복사한 뒤에는 눈으로만 믿지 않는다.
md5sum /data/dump.sql /backup/dump.sql
함정과 주의점
대상 디렉토리가 있느냐 없느냐로 결과가 달라진다. 실무에서 가장 자주 헷갈리는 지점이다.
cp -r src dst # dst가 없으면 → dst 가 src의 복사본이 된다
cp -r src dst # dst가 있으면 → dst/src 가 만들어진다
백업을 두 번 돌렸더니 /backup/app/app이 생기는 이유가 이것이다. 의도를 분명히 하려면 내용만 옮기는 cp -a src/. dst/ 형태를 쓴다.
cp는 묻지 않고 덮어쓴다. 운영 설정을 사본으로 덮어써 되돌릴 수 없게 되는 사고가 흔하다. 대화형으로 작업할 때는 -i, 스크립트에서는 -n이나 --backup=numbered를 붙인다. 참고로 -i는 -f·-n과 함께 쓰면 뒤에 온 옵션이 이긴다.
root로 복사하면 소유자가 root로 바뀐다. -p나 -a 없이 복사한 파일은 실행한 계정 소유가 되고 퍼미션도 umask를 탄다. 서비스 계정이 읽던 파일을 root로 복사해 놓고 "권한 오류"에 빠지는 경우가 많다. 서비스 파일을 다룰 때는 -a를 기본으로 쓴다.
심볼릭 링크 처리는 구현마다 다르다. GNU coreutils의 cp -r은 링크를 링크 그대로 복사하지만, macOS·BSD의 cp -r은 링크가 가리키는 실제 파일을 복사한다. 결과가 달라지지 않게 하려면 링크를 유지할 때 -a(또는 -P), 실체를 복사할 때 -L을 명시한다.
큰 디렉토리는 cp로 옮기지 마라. 수십 GB를 cp -a로 복사하다 세션이 끊기면 어디까지 됐는지 알 수 없고, 다시 돌리면 처음부터다. rsync -a --info=progress2 src/ dst/는 중단돼도 이어받고, 진행률도 보이고, 끝난 뒤 차이 검증도 된다.
함께 보면 좋은 명령어
- rsync — 이어받기·진행률·차이 비교가 필요한 모든 복사. 서버 간 전송도 담당한다.
- mv — 같은 파일시스템 안이라면 복사 없이 이름만 바꾸므로 즉시 끝난다.
- install — 복사와 동시에 소유자·권한을 지정한다. 배포 스크립트에서
cp+chown+chmod를 한 줄로 대체한다.