파일처리_18 파일 퍼미션과 타임 스탬프 등 원래 파일 속성을 유지한 채 파일 복사하기

 
  • 출처 : 유닉스 리눅스 쉘스크립트 예제사전_한빛미디어

명령어: getopts, cp
키워드: 복사, 백업, 파일 속성, 심볼릭 링크
사용처: 디렉터리를 복사할 때 파일 속성과 심볼릭 링크를 포함해서 백업하고 싶을 때


실행예제

 $ ./cp-p.sh -a

스크립트

#!/bin/sh
 
backup dir="home/user1/backup"
 
# myapp 디렉터리를 $backup_dir 밑에 백업 복사
while getopts "a" option
do
    case $option in
        a)
            cp -a myapp "$backup_dir"
            exit
            ;;
    esac
done
 
cp -R myapp "$backup_dir"

   

해설

이 스크립트는 현재 디렉터리에 있는 myapp 디렉터리 아래에 있는 파일과, 디렉터리 전체를 셸 변수 backup_dir로 지정한 디렉터리로 복사해서 백업합니다. 이때 -a 옵션을 지정하면 파일의 타임스탬프와 퍼미션 등 파일 속성을 유지한 채 복사합니다.

예제에서는 getopts 명령어를 써서 셸 스크립트 옵션 지정을 판별합니다. 여기서 -a를 지정하면 cp 명령어-a 옵션으로 실행해서 타임스탬프와 퍼미션을 유지하며 복사합니다. 옵션을 지정하지 않으면 cp 명령어를 -R 옵션으로 실행해서 파일 복사만 수행합니다. 이것은 예를 들어 복사한 날짜를 명시하고 싶어서 타임스탬프를 유지하지 않도록 하는 경우를 들 수 있습니다.

cp 명령어는 옵션 없이 파일을 복사하면 파일 퍼미션은 umask로 설정한 값으로 변합니다. 또한 타임스탬프는 현재 시각으로 변경됩니다. 그리고 옵션 없는 cp 명령어는 디렉터리를 복사하지 않습니다. 백업 용도로 디렉터리째 복사할 때 주의해야 합니다.   -a 옵션을 붙이면 cp 명령어는 원본 파일의 소유자, 그룹, 접근권, 접근 시각 등 파일 속성을 유지한 채 파일을 복사합니다. 따라서 백업 용도로 자주 사용합니다. 또한 -a 옵션을 사용하면 -R(recursive) 옵션도 동시에 지정한 것으로 봐서 서브디렉터리를 포함한 파일 트리를 그대로 복사합니다.

-R 옵션에 심볼릭 링크는 링크 자체를 복사합니다. 만약 심볼릭 링크가 가리키는 실제 파일을 복사하고 싶으면 -R과 -L 옵션을 같이 사용합니다. 또한 -p(preserve) 옵션을 지정하면 파일 속성도 유지할 수 있습니다.

cp -pRL myapp "$backup_dir"

한편 cp 명령어의 man을 보면 -a 옵션은 -p 옵션에 몇 가지 옵션을 조합한 것입니다. cp 명령어의 -a 옵션은 OS에 따라 다소 동작이 다릅니다.

  • 리눅스에서는 -a는 -dpR과 같습니다. -d는 심볼릭 링크를 심볼릭 링크로 그대로 복사하는 것을 의미합니다.

  • FreeBSD와 Mac이라면 -a는 -RpP와 같습니다. -P는 심볼릭 링크를 심볼릭 링크로 복사하는 것을 의미합니다.

  백업 스크립트에서 -a 옵션 대신 -p 옵션과 -R 옵션을 사용하는 것도 일반적입니다. 그런데 다음처럼 소문자 -r을 사용한 스크립트도 종종 보게 됩니다.

cp -pr myapp "$backup_dir"

하지만 소문자 -r 옵션은 리눅스에서는 심볼릭 링크를 그대로 링크로 복사하지만 Mac이나 FreeBSD에서는 심볼릭 링크가 가리키는 실제 파일을 복사합니다. 따라서 BSD 계열 시스템이라면 cp 명령어 -r 옵션을 쓰지 말고 -R 옵션을 사용하기 바랍니다.

   

주의사항

  • 복사 원본 파일의 스크립트 실행자와 파일 소유자가 다르면 속성을 유지 못할 수도 있습니다. 예를 들어 소유자가 root인 파일을 일반 사용자가 -p 옵션으로 cp 명령어를 실행해도 일반 사용자가 파일 소유자를 root로 만들 수 없으므로 파일 소유자 속성은 cp 명령어를 실행한 사용자가 됩니다. 하지만 파일 타임스탬프 등의 정보는 이어집니다.

  • root가 소유한 파일을 일반 사용자가 -a 옵션으로 복사한 경우

      $ ls -l
      total 0
      -rw-r--r--1 root root 0 Dec 6 22:55 test.txt
    
      $ cp -a test.txt my.txt
      $ ls -l
      total 0
      -rw-r--r--1 user1 user1 0 Dec 6 22:55 my.txt # -- notice
      -rw-r--r--1 root root 0 Dec 6 22:55 test.txt
    

    notice a옵션 cp명령어로 복사했지만 my.txt 소유자는 root가 아닌 user1

  • 마찬가지로 파일 그룹 속성이 자신이 속하지 않은 그룹일 때 root 권한이 아니라면 그룹 속성을 그대로 복사할 수 없습니다.