`shutil` — 고수준 파일 연산

shutil — 고수준 파일 연산

소스 코드: Lib/shutil.py

shutil 모듈은 파일과 파일 집합에 대한 다양한 고수준 연산을 제공해요. 특히 파일 복사와 삭제를 지원하는 함수들이 있어요. 개별 파일에 대한 연산은 os 모듈도 참고하세요.

출처: Python 표준 라이브러리

본문

경고: 더 고수준의 파일 복사 함수(shutil.copy(), shutil.copy2())조차 모든 파일 메타데이터를 복사할 수 없어요. POSIX 플랫폼에서는 파일 소유자와 그룹, ACL이 유실되고, Mac OS에서는 리소스 포크(resource fork)와 기타 메타데이터가 사용되지 않아요. 즉 리소스가 유실되고 파일 종류·생성자 코드가 올바르지 않게 돼요. Windows에서는 파일 소유자, ACL, 대체 데이터 스트림(alternate data streams)이 복사되지 않아요.

디렉터리 및 파일 연산

shutil.copyfileobj(*fsrc*, *fdst*[, *length*])

file-like 객체 fsrc 의 내용을 file-like 객체 fdst 에 복사해요. 정수 length 가 주어지면 버퍼 크기예요. 특히 length 가 음수이면 소스 데이터를 청크(chunk)로 나누지 않고 통째로 복사한다는 뜻이에요. 기본적으로는 메모리를 과도하게 쓰지 않도록 데이터를 청크로 나눠 읽어요. fsrc 객체의 현재 파일 위치가 0이 아니면, 현재 파일 위치부터 파일 끝까지의 내용만 복사된다는 점에 주의하세요.

copyfileobj() 는 복사가 끝났을 때 대상 스트림이 flush될 것을 보장하지 않아요. 복사가 끝난 뒤 대상에서 읽고 싶다면(예: HTTP 스트림에서 복사한 임시 파일 내용을 읽는 경우), 대상 파일을 읽기 전에 file-like 객체에 flush()close() 를 호출했는지 확인해야 해요.

shutil.copyfile(*src*, *dst*, *, *follow_symlinks=True*)

src 라는 파일의 내용(메타데이터 없음)을 dst 라는 파일에 가능한 한 가장 효율적인 방식으로 복사하고 dst 를 반환해요. srcdst 는 path-like 객체이거나 문자열로 주어진 경로 이름이에요.

dst 는 완전한 대상 파일 이름이어야 해요. 대상 디렉터리 경로를 받는 복사는 copy() 를 참고하세요. srcdst 가 같은 파일이면 SameFileError 가 발생해요.

대상 위치는 쓰기 가능해야 해요. 그렇지 않으면 OSError 예외가 발생해요. dst 가 이미 존재하면 덮어쓰여요. 문자/블록 장치나 파이프 같은 특수 파일은 이 함수로 복사할 수 없어요.

follow_symlinks 가 false이고 src 가 심볼릭 링크라면, src 가 가리키는 파일을 복사하는 대신 새 심볼릭 링크를 만들어요.

인자 src, dst와 함께 감사 이벤트 shutil.copyfile 을 발생시켜요.

3.3 버전 변경: OSError 대신 IOError 가 발생하곤 했어요. follow_symlinks 인자가 추가됐고, 이제 dst 를 반환해요.

3.4 버전 변경: Error 대신 SameFileError 를 발생시켜요. 전자가 후자의 서브클래스이므로 이 변경은 하위 호환돼요.

3.8 버전 변경: 파일을 더 효율적으로 복사하기 위해 플랫폼별 fast-copy syscall이 내부적으로 사용될 수 있어요. Platform-dependent efficient copy operations 절을 참고하세요.

예외 shutil.SpecialFileError

copyfile() 또는 copytree() 가 named pipe를 복사하려고 할 때 발생하는 예외예요.

2.7 버전에서 추가.

예외 shutil.SameFileError

copyfile() 의 출처와 대상이 같은 파일일 때 발생하는 예외예요.

3.4 버전에서 추가.

shutil.copymode(*src*, *dst*, *, *follow_symlinks=True*)

src 의 권한 비트(permission bits)를 dst 에 복사해요. 파일 내용, 소유자, 그룹은 영향을 받지 않아요. srcdst 는 path-like 객체이거나 문자열로 주어진 경로 이름이에요.

follow_symlinks 가 false이고 srcdst 가 모두 심볼릭 링크라면, copymode() 는 (링크가 가리키는 파일이 아니라) dst 자체의 모드를 수정하려고 시도해요. 이 기능은 모든 플랫폼에서 사용할 수 있는 건 아니에요. 자세한 내용은 copystat() 를 참고하세요. 로컬 플랫폼이 심볼릭 링크를 수정할 수 없는데 그렇게 하도록 요청받으면 아무것도 하지 않고 반환해요.

인자 src, dst와 함께 감사 이벤트 shutil.copymode 를 발생시켜요.

3.3 버전 변경: follow_symlinks 인자가 추가됐어요.

shutil.copystat(*src*, *dst*, *, *follow_symlinks=True*)

src 의 권한 비트, 마지막 접근 시간, 마지막 수정 시간, 플래그를 dst 에 복사해요. Linux에서 copystat() 는 가능하면 "확장 속성(extended attributes)"도 복사해요. 파일 내용, 소유자, 그룹은 영향을 받지 않아요. srcdst 는 path-like 객체이거나 문자열로 주어진 경로 이름이에요.

follow_symlinks 가 false이고 srcdst 가 모두 심볼릭 링크를 가리킨다면, copystat() 는 심볼릭 링크가 가리키는 파일이 아니라 심볼릭 링크 자체에 대해 동작해요. src 심볼릭 링크에서 정보를 읽고 dst 심볼릭 링크에 정보를 써요.

참고: 모든 플랫폼이 심볼릭 링크를 검사하고 수정하는 기능을 제공하지는 않아요. Python 자체가 로컬에서 어떤 기능을 쓸 수 있는지 알려줄 수 있어요.

  • os.chmod in os.supports_follow_symlinksTrue 이면, copystat() 는 심볼릭 링크의 권한 비트를 수정할 수 있어요.
  • os.utime in os.supports_follow_symlinksTrue 이면, copystat() 는 심볼릭 링크의 마지막 접근·수정 시간을 수정할 수 있어요.
  • os.chflags in os.supports_follow_symlinksTrue 이면, copystat() 는 심볼릭 링크의 플래그를 수정할 수 있어요.(os.chflags 는 모든 플랫폼에서 쓸 수 있는 건 아니에요.)

이 기능 중 일부 또는 전부를 쓸 수 없는 플랫폼에서 심볼릭 링크를 수정하도록 요청받으면 copystat() 는 할 수 있는 만큼 복사해요. copystat() 는 절대 실패를 반환하지 않아요.

자세한 내용은 os.supports_follow_symlinks 를 참고하세요.

인자 src, dst와 함께 감사 이벤트 shutil.copystat 을 발생시켜요.

3.3 버전 변경: follow_symlinks 인자와 Linux 확장 속성 지원이 추가됐어요.

shutil.copy(*src*, *dst*, *, *follow_symlinks=True*)

파일 src 를 파일 또는 디렉터리 dst 에 복사해요. srcdst 는 path-like 객체 또는 문자열이어야 해요. dst 가 디렉터리를 지정하면 파일은 src 의 기본 파일 이름을 사용해 dst 안으로 복사돼요. dst 가 이미 존재하는 파일을 지정하면 덮어써져요. 새로 만들어진 파일의 경로를 반환해요.

follow_symlinks 가 false이고 src 가 심볼릭 링크라면 dst 는 심볼릭 링크로 생성돼요. follow_symlinks 가 true이고 src 가 심볼릭 링크라면 dstsrc 가 가리키는 파일의 복사본이 돼요.

copy() 는 파일 데이터와 파일의 권한 모드(permission mode, os.chmod() 참고)를 복사해요. 파일 생성·수정 시간 같은 다른 메타데이터는 보존되지 않아요. 원본의 모든 파일 메타데이터를 보존하려면 대신 copy2() 를 사용하세요.

인자 src, dst와 함께 감사 이벤트 shutil.copyfile 을 발생시켜요.

인자 src, dst와 함께 감사 이벤트 shutil.copymode 를 발생시켜요.

3.3 버전 변경: follow_symlinks 인자가 추가됐고 이제 새로 만들어진 파일의 경로를 반환해요.

3.8 버전 변경: 파일을 더 효율적으로 복사하기 위해 플랫폼별 fast-copy syscall이 내부적으로 사용될 수 있어요. Platform-dependent efficient copy operations 절을 참고하세요.

shutil.copy2(*src*, *dst*, *, *follow_symlinks=True*)

copy() 와 동일하지만, copy2() 는 파일 메타데이터 보존도 시도한다는 점이 달라요.

follow_symlinks 가 false이고 src 가 심볼릭 링크일 때 copy2()src 심볼릭 링크의 모든 메타데이터를 새로 만들어진 dst 심볼릭 링크에 복사하려고 시도해요. 그러나 이 기능은 모든 플랫폼에서 사용할 수 있는 건 아니에요. 기능의 일부 또는 전부를 쓸 수 없는 플랫폼에서 copy2() 는 할 수 있는 모든 메타데이터를 보존해요. copy2() 는 파일 메타데이터를 보존하지 못했다고 해서 예외를 발생시키지 않아요.

copy2() 는 파일 메타데이터를 복사할 때 copystat() 를 사용해요. 심볼릭 링크 메타데이터 수정의 플랫폼 지원에 대한 자세한 내용은 copystat() 를 참고하세요.

인자 src, dst와 함께 감사 이벤트 shutil.copyfile 을 발생시켜요.

인자 src, dst와 함께 감사 이벤트 shutil.copystat 을 발생시켜요.

3.3 버전 변경: follow_symlinks 인자가 추가됐고, 확장 파일 시스템 속성도 복사하려고 시도해요(현재 Linux 전용). 이제 새로 만들어진 파일의 경로를 반환해요.

3.8 버전 변경: 파일을 더 효율적으로 복사하기 위해 플랫폼별 fast-copy syscall이 내부적으로 사용될 수 있어요. Platform-dependent efficient copy operations 절을 참고하세요.

shutil.ignore_patterns(* *patterns*)

이 팩토리 함수는 copytree()ignore 인자로 쓸 수 있는 호출 가능 객체를 만들어요. 주어진 glob 스타일 patterns 중 하나와 일치하는 파일과 디렉터리를 무시해요. 아래 예시를 참고하세요.

shutil.copytree(*src*, *dst*, *symlinks=False*, *ignore=None*, *copy_function=copy2*, *ignore_dangling_symlinks=False*, *dirs_exist_ok=False*)

src 를 루트로 하는 전체 디렉터리 트리를 dst 라는 디렉터리에 재귀적으로 복사하고 대상 디렉터리를 반환해요. dst 를 담는 데 필요한 모든 중간 디렉터리도 기본적으로 생성돼요.

디렉터리의 권한과 시간은 copystat() 로 복사되고, 개별 파일은 copy2() 로 복사돼요.

symlinks 가 true이면 소스 트리의 심볼릭 링크가 새 트리에서 심볼릭 링크로 표현되고, 원본 링크의 메타데이터는 플랫폼이 허용하는 한 복사돼요. false이거나 생략하면 링크된 파일의 내용과 메타데이터가 새 트리에 복사돼요.

symlinks 가 false일 때, 심볼릭 링크가 가리키는 파일이 존재하지 않으면 복사 과정이 끝날 때 Error 예외에서 발생한 오류 목록에 예외가 추가돼요. 이 예외를 조용히 처리하고 싶으면 선택적인 ignore_dangling_symlinks 플래그를 true로 설정할 수 있어요. 이 옵션은 os.symlink() 를 지원하지 않는 플랫폼에서는 효과가 없어요.

ignore 가 주어지면 호출 가능 객체여야 하며, copytree() 가 방문하는 디렉터리와 os.listdir() 이 반환한 그 내용 목록을 인자로 받아요. copytree() 는 재귀적으로 호출되므로 ignore callable은 복사되는 각 디렉터리에 대해 한 번씩 호출돼요. 이 callable은 현재 디렉터리 기준의 디렉터리·파일 이름 시퀀스(즉 두 번째 인자 항목들의 부분집합)를 반환해야 하며, 그 이름들은 복사 과정에서 무시돼요. ignore_patterns() 를 사용해 glob 스타일 패턴에 따라 이름을 무시하는 그런 callable을 만들 수 있어요.

예외가 발생하면 이유 목록과 함께 Error 가 발생해요.

copy_function 이 주어지면 각 파일을 복사하는 데 쓰일 callable이어야 해요. 소스 경로와 대상 경로를 인자로 받아 호출돼요. 기본적으로 copy2() 가 쓰이지만, 같은 시그니처를 지원하는 어떤 함수(copy() 같은)도 쓸 수 있어요.

dirs_exist_ok 가 false(기본값)이고 dst 가 이미 존재하면 FileExistsError 가 발생해요. dirs_exist_ok 가 true이면 복사 작업이 기존 디렉터리를 만나도 계속 진행되고, dst 트리 안의 파일은 src 트리의 대응 파일로 덮어써져요.

인자 src, dst와 함께 감사 이벤트 shutil.copytree 를 발생시켜요.

3.2 버전 변경: 사용자 정의 복사 함수를 제공할 수 있는 copy_function 인자와, symlinks 가 false일 때 dangling symlink 오류를 조용히 처리하는 ignore_dangling_symlinks 인자가 추가됐어요.

3.3 버전 변경: symlinks 가 false일 때 메타데이터를 복사해요. 이제 dst 를 반환해요.

3.8 버전 변경: 파일을 더 효율적으로 복사하기 위해 플랫폼별 fast-copy syscall이 내부적으로 사용될 수 있어요. Platform-dependent efficient copy operations 절을 참고하세요.

3.8 버전 변경: dirs_exist_ok 매개변수가 추가됐어요.

shutil.rmtree(*path*, *ignore_errors=False*, *onerror=None*, *, *onexc=None*, *dir_fd=None*)

전체 디렉터리 트리를 삭제해요. path 는 디렉터리를 가리켜야 해요(디렉터리에 대한 심볼릭 링크는 안 됨). ignore_errors 가 true이면 제거 실패로 인한 오류는 무시돼요. false이거나 생략하면 그런 오류는 onexconerror 로 지정한 핸들러가 처리하고, 둘 다 생략하면 예외가 호출자에게 전파돼요.

이 함수는 디렉터리 디스크립터에 상대적인 경로를 지원할 수 있어요.

참고: 필요한 fd 기반 함수를 지원하는 플랫폼에서는 symlink 공격에 저항하는 버전의 rmtree() 가 기본으로 사용돼요. 다른 플랫폼에서는 rmtree() 구현이 symlink 공격에 취약해요. 적절한 타이밍과 상황이 주어지면 공격자는 파일시스템의 심볼릭 링크를 조작해 평소에는 접근할 수 없는 파일을 삭제할 수 있어요. 애플리케이션은 rmtree.avoids_symlink_attacks 함수 속성으로 어느 경우인지 판단할 수 있어요.

onexc 가 제공되면 세 매개변수 function, path, excinfo 를 받는 callable이어야 해요.

첫 매개변수 function 은 예외를 발생시킨 함수로, 플랫폼과 구현에 따라 달라요. 둘째 매개변수 pathfunction 에 전달된 경로 이름이에요. 셋째 매개변수 excinfo 는 발생한 예외예요. onexc 가 발생시킨 예외는 잡히지 않아요.

비권장된 onerroronexc 와 비슷하지만, 받는 셋째 매개변수가 sys.exc_info() 가 반환한 튜플이라는 점이 달라요.

참고: 읽기 전용 파일을 포함한 디렉터리 트리의 제거를 처리하는 예시는 rmtree example 을 참고하세요.

인자 path, dir_fd 와 함께 감사 이벤트 shutil.rmtree 를 발생시켜요.

3.3 버전 변경: fd 기반 함수를 지원하는 플랫폼에서 자동으로 사용되는 symlink 공격 저항 버전이 추가됐어요.

3.8 버전 변경: Windows에서 디렉터리 정션(junction)을 제거하기 전에 그 내용을 더 이상 삭제하지 않아요.

3.11 버전 변경: dir_fd 매개변수가 추가됐어요.

3.12 버전 변경: onexc 매개변수가 추가됐고 onerror 가 비권장됐어요.

3.13 버전 변경: rmtree() 는 이제 최상위 경로를 제외한 모든 경로에 대해 FileNotFoundError 예외를 무시해요. OSError 및 그 서브클래스 외의 예외는 이제 항상 호출자에게 전파돼요.

rmtree.avoids_symlink_attacks

현재 플랫폼과 구현이 symlink 공격에 저항하는 버전의 rmtree() 를 제공하는지 나타내요. 현재는 fd 기반 디렉터리 접근 함수를 지원하는 플랫폼에서만 true예요.

3.3 버전에서 추가.

shutil.move(*src*, *dst*, *copy_function=copy2*)

파일 또는 디렉터리(src)를 다른 위치로 재귀적으로 이동하고 대상 위치를 반환해요.

dst 가 기존 디렉터리이거나 디렉터리에 대한 심볼릭 링크라면 src 는 그 디렉터리 안으로 이동돼요. 그 디렉터리 안의 대상 경로는 아직 존재하지 않아야 해요.

dst 가 이미 존재하지만 디렉터리가 아니라면, os.rename() 의미에 따라 덮어써질 수 있어요.

src 와 대상이 같은 파일시스템에 있으면 내부적으로 os.rename() 이 선호돼요. os.rename()OSError 로 인해 실패하면(예: 대상 파일에는 쓰기 권한이 있는데 부모 디렉터리에는 없는 경우) 이 메서드는 copy_function 을 사용하는 방식으로 돌아가는데, 이 경우 srccopy_function 으로 대상에 복사된 다음 제거돼요.

심볼릭 링크의 경우, src 의 대상을 가리키는 새 심볼릭 링크가 대상 위치에 생성되고 src 는 제거돼요.

copy_function 이 주어지면 두 인자 src 와 대상 경로를 받는 callable이어야 하며, os.rename() 을 쓸 수 없을 때 src 를 대상에 복사하는 데 사용돼요. 소스가 디렉터리라면 copy_function 을 전달하며 copytree() 가 호출돼요. 기본 copy_functioncopy2() 예요. copy_function 으로 copy() 를 쓰면 메타데이터를 복사할 수 없을 때도 이동이 성공할 수 있지만, 메타데이터는 전혀 복사되지 않아요.

인자 src, dst와 함께 감사 이벤트 shutil.move 를 발생시켜요.

3.3 버전 변경: 외부 파일시스템에 대한 명시적 심볼릭 링크 처리가 추가돼 GNU의 mv 동작에 맞췄어요. 이제 dst 를 반환해요.

3.5 버전 변경: copy_function 키워드 인자가 추가됐어요.

3.8 버전 변경: 파일을 더 효율적으로 복사하기 위해 플랫폼별 fast-copy syscall이 내부적으로 사용될 수 있어요. Platform-dependent efficient copy operations 절을 참고하세요.

3.9 버전 변경: srcdst 모두에 대해 path-like 객체를 받아요.

shutil.disk_usage(*path*)

주어진 경로에 대한 디스크 사용량 통계를 named tuple로 반환해요. 속성은 total, used, free 이고, 각각 바이트 단위의 전체·사용·여유 공간이에요. path 는 파일일 수도 디렉터리일 수도 있어요.

참고: Unix 파일시스템에서 path마운트된 파일시스템 파티션 안의 경로를 가리켜야 해요. 그런 플랫폼에서 CPython은 마운트되지 않은 파일시스템의 디스크 사용량 정보를 가져오려고 시도하지 않아요.

3.3 버전에서 추가.

3.8 버전 변경: Windows에서 path 는 이제 파일 또는 디렉터리일 수 있어요.

가용성: Unix, Windows.

shutil.chown(*path*, *user=None*, *group=None*, *, *dir_fd=None*, *follow_symlinks=True*)

주어진 path 의 소유자 user 및/또는 그룹 group 을 변경해요.

user 는 시스템 사용자 이름 또는 uid일 수 있고 group 도 마찬가지예요. 최소한 하나의 인자는 필요해요.

기반 함수인 os.chown() 도 참고하세요.

인자 path, user, group 와 함께 감사 이벤트 shutil.chown 을 발생시켜요.

가용성: Unix.

3.3 버전에서 추가.

3.13 버전 변경: dir_fdfollow_symlinks 매개변수가 추가됐어요.

shutil.which(*cmd*, *mode=os.F_OK | os.X_OK*, *path=None*)

주어진 cmd 가 호출되면 실행될 실행 파일의 경로를 반환해요. 호출될 cmd 가 없으면 None 을 반환해요.

modeos.access() 에 전달되는 권한 마스크로, 기본적으로 파일이 존재하고 실행 가능한지 판별해요.

path 는 찾을 디렉터리를 지정하는 "PATH 문자열"이고 os.pathsep 로 구분돼요. path 를 지정하지 않으면 os.environ 에서 PATH 환경 변수를 읽고, 설정돼 있지 않으면 os.defpath 로 대체해요.

cmd 가 디렉터리 구성 요소를 포함하면 which() 는 지정된 경로만 직접 확인하고 path 나 시스템의 PATH 환경 변수에 나열된 디렉터리는 검색하지 않아요.

Windows에서 modeos.X_OK 를 포함하지 않으면 현재 디렉터리가 path 앞에 붙어요. modeos.X_OK 를 포함하면 Windows API NeedCurrentDirectoryForExePathW 를 참조해 현재 디렉터리를 path 앞에 붙일지 판단해요. 실행 파일을 위해 현재 작업 디렉터리를 참조하지 않으려면 환경 변수 NoDefaultCurrentDirectoryInExePath 를 설정하세요.

또한 Windows에서는 확장자가 아직 없는 명령을 해석하기 위해 PATHEXT 환경 변수가 사용돼요. 예를 들어 shutil.which("python") 을 호출하면 which()PATHEXT 를 검색해 path 디렉터리 안에서 python.exe 를 찾아야 한다는 걸 알게 돼요. 예를 들어 Windows에서:

>>> shutil.which("python")
'C:\\Python33\\python.EXE'

이것은 cmd 가 디렉터리 구성 요소를 포함하는 경로일 때도 적용돼요:

>>> shutil.which("C:\\Python33\\python")
'C:\\Python33\\python.EXE'

3.3 버전에서 추가.

3.8 버전 변경: bytes 형식이 이제 허용돼요. cmd 형식이 bytes 이면 결과 형식도 bytes 예요.

3.12 버전 변경: Windows에서 modeos.X_OK 를 포함하고 WinAPI NeedCurrentDirectoryForExePathW(cmd) 가 false이면 현재 디렉터리가 더 이상 검색 경로 앞에 붙지 않고, 그 외에는 현재 디렉터리가 이미 검색 경로에 있더라도 앞에 붙어요. 이제 cmd 가 디렉터리 구성 요소를 포함하거나 PATHEXT 에 있는 확장자로 끝나는 경우에도 PATHEXT 가 사용되고, 확장자가 없는 파일 이름도 찾을 수 있어요.

예외 shutil.Error

이 예외는 다중 파일 연산 중 발생한 예외들을 모아요. copytree() 의 경우 예외 인자는 3-튜플들의 리스트 (srcname, dstname, exception) 이에요.

플랫폼 의존적 효율적인 복사 연산

Python 3.8부터 파일 복사를 포함하는 모든 함수(copyfile(), copy(), copy2(), copytree(), move())가 파일을 더 효율적으로 복사하기 위해 플랫폼별 "fast-copy" syscall을 사용할 수 있어요(bpo-33671 참고). "fast-copy"란 복사 연산이 커널 안에서 일어나서 Python의 사용자 공간 버퍼("outfd.write(infd.read())" 같은)를 사용하지 않는다는 뜻이에요.

  • macOS에서는 파일 내용(메타데이터 아님)을 복사하는 데 fcopyfile 이 사용돼요.
  • Linux에서는 os.copy_file_range() 또는 os.sendfile() 이 사용돼요.
  • Solaris에서는 os.sendfile() 이 사용돼요.
  • Windows에서는 shutil.copyfile() 이 더 큰 기본 버퍼 크기(64 KiB 대신 1 MiB)를 사용하고, memoryview() 기반의 shutil.copyfileobj() 변형이 사용돼요.

fast-copy 연산이 실패하고 대상 파일에 데이터가 쓰이지 않았다면 shutil은 내부적으로 덜 효율적인 copyfileobj() 함수로 조용히 대체해요.

3.8 버전 변경.

3.14 버전 변경: Solaris가 이제 os.sendfile() 을 사용해요.

3.14 버전 변경: 지원되는 Linux 파일시스템에서 os.copy_file_range() 를 통해 내부적으로 copy-on-write 또는 서버 측 복사가 사용될 수 있어요.

copytree 예제

ignore_patterns() 헬퍼를 사용하는 예제예요:

from shutil import copytree, ignore_patterns

copytree(source, destination, ignore=ignore_patterns('*.pyc', 'tmp*'))

이것은 *.pyc 파일과 이름이 tmp 로 시작하는 파일이나 디렉터리를 제외한 모든 것을 복사해요.

ignore 인자를 사용해 로깅 호출을 추가하는 또 다른 예제예요:

from shutil import copytree
import logging

def _logpath(path, names):
    logging.info('Working in %s', path)
    return []   # nothing will be ignored

copytree(source, destination, ignore=_logpath)

rmtree 예제

이 예제는 일부 파일에 읽기 전용 비트가 설정된 Windows에서 디렉터리 트리를 제거하는 방법을 보여줘요. onexc 콜백을 사용해 읽기 전용 비트를 해제하고 제거를 다시 시도해요. 이후의 어떤 실패도 전파돼요.

import os, stat
import shutil

def remove_readonly(func, path, _):
    "Clear the readonly bit and reattempt the removal"
    os.chmod(path, stat.S_IWRITE)
    func(path)

shutil.rmtree(directory, onexc=remove_readonly)

아카이빙 연산

3.2 버전에서 추가.

3.5 버전 변경: xztar 형식 지원이 추가됐어요.

압축되고 아카이브된 파일을 만들고 읽기 위한 고수준 유틸리티도 제공돼요. 이들은 zipfiletarfile 모듈에 의존해요.

shutil.make_archive(*base_name*, *format*[, *root_dir*[, *base_dir*[, *verbose*[, *dry_run*[, *owner*[, *group*[, *logger*]]]]]]])

아카이브 파일(zip이나 tar 같은)을 만들고 그 이름을 반환해요.

base_name 은 만들 파일의 이름으로, 경로를 포함하고 형식별 확장자는 뺀 것이에요.

format 은 아카이브 형식으로, "zip"(zlib 모듈이 있으면), "tar", "gztar"(zlib 모듈이 있으면), "bztar"(bz2 모듈이 있으면), "xztar"(lzma 모듈이 있으면), 또는 "zstdtar"(compression.zstd 모듈이 있으면) 중 하나예요.

root_dir 은 아카이브의 루트 디렉터리가 될 디렉터리로, 아카이브의 모든 경로는 그에 상대적이에요. 예를 들어 보통 아카이브를 만들기 전에 root_dir 로 chdir해요.

base_dir 은 아카이빙을 시작하는 디렉터리예요. 즉 base_dir 이 아카이브에 있는 모든 파일·디렉터리의 공통 접두사가 돼요. base_dirroot_dir 에 상대적으로 주어져야 해요. base_dirroot_dir 을 함께 쓰는 방법은 Archiving example with base_dir 을 참고하세요.

root_dirbase_dir 은 둘 다 기본적으로 현재 디렉터리예요.

dry_run 이 true이면 아카이브를 만들지 않지만, 실행될 연산은 logger 에 기록돼요.

ownergroup 은 tar 아카이브를 만들 때 사용돼요. 기본적으로 현재 소유자와 그룹을 사용해요.

loggerPEP 282 와 호환되는 객체여야 하고, 보통 logging.Logger 인스턴스예요.

verbose 인자는 사용되지 않으며 비권장돼요.

인자 base_name, format, root_dir, base_dir 와 함께 감사 이벤트 shutil.make_archive 를 발생시켜요.

참고: register_archive_format() 으로 등록된 사용자 정의 아카이버가 root_dir 인자를 지원하지 않을 때 이 함수는 스레드 안전하지 않아요. 이 경우 아카이빙을 수행하기 위해 프로세스의 현재 작업 디렉터리를 root_dir 로 일시적으로 변경해요.

3.8 버전 변경: format="tar" 로 만든 아카이브에 기존 GNU 형식 대신 현대적인 pax(POSIX.1-2001) 형식이 사용돼요.

3.10.6 버전 변경: 이 함수는 이제 표준 .zip 및 tar 아카이브 생성 중에 스레드 안전해졌어요.

shutil.get_archive_formats()

아카이빙을 위해 지원되는 형식 목록을 반환해요. 반환된 시퀀스의 각 요소는 튜플 (name, description) 이에요.

기본적으로 shutil 은 다음 형식을 제공해요:

  • zip: ZIP 파일(zlib 모듈이 있으면).
  • tar: 압축되지 않은 tar 파일. 새 아카이브에 POSIX.1-2001 pax 형식을 사용.
  • gztar: gzip으로 압축된 tar 파일(zlib 모듈이 있으면).
  • bztar: bzip2로 압축된 tar 파일(bz2 모듈이 있으면).
  • xztar: xz로 압축된 tar 파일(lzma 모듈이 있으면).
  • zstdtar: Zstandard로 압축된 tar 파일(compression.zstd 모듈이 있으면).

register_archive_format() 을 사용해 새 형식을 등록하거나 기존 형식에 자신만의 아카이버를 제공할 수 있어요.

shutil.register_archive_format(*name*, *function*[, *extra_args*[, *description*]])

형식 name 에 대한 아카이버를 등록해요.

function 은 아카이브를 만드는 데 쓰일 callable이에요. 이 callable은 만들 파일의 base_name 을 받고, 이어서 아카이빙을 시작할 base_dir(기본값 os.curdir)을 받아요. 추가 인자는 키워드 인자로 전달돼요: owner, group, dry_run, logger(make_archive() 에 전달된 것처럼).

function 이 사용자 정의 속성 function.supports_root_dirTrue 로 설정하고 있으면 root_dir 인자가 키워드 인자로 전달돼요. 그렇지 않으면 function 을 호출하기 전에 프로세스의 현재 작업 디렉터리를 root_dir 로 일시적으로 변경해요. 이 경우 make_archive() 는 스레드 안전하지 않아요.

주어지면 extra_args 는 아카이버 callable을 사용할 때 추가 키워드 인자로 쓰일 (name, value) 쌍들의 시퀀스예요.

description 은 아카이버 목록을 반환하는 get_archive_formats() 에서 사용돼요. 기본값은 빈 문자열이에요.

3.12 버전 변경: root_dir 인자를 지원하는 함수에 대한 지원이 추가됐어요.

shutil.unregister_archive_format(*name*)

지원되는 형식 목록에서 아카이브 형식 name 을 제거해요.

shutil.unpack_archive(*filename*[, *extract_dir*[, *format*[, *filter*]]])

아카이브를 풀어요. filename 은 아카이브의 전체 경로예요.

extract_dir 은 아카이브가 풀리는 대상 디렉터리의 이름이에요. 제공하지 않으면 현재 작업 디렉터리가 사용돼요.

format 은 아카이브 형식으로, "zip", "tar", "gztar", "bztar", "xztar", "zstdtar" 중 하나예요. 또는 register_unpack_format() 으로 등록된 다른 형식일 수 있어요. 제공하지 않으면 unpack_archive() 는 아카이브 파일 이름 확장자를 사용해 그 확장자에 등록된 해제기를 찾아봐요. 찾지 못하면 ValueError 가 발생해요.

키워드 전용 filter 인자는 내부 언패킹 함수로 전달돼요. zip 파일의 경우 filter 는 받지 않아요. tar 파일의 경우 Python 3.14부터 기본인 'data' 를 권장하며, tar 및 Unix 계열 파일시스템 고유의 기능을 쓸 때가 아니라면 그렇게 해요(자세한 내용은 Extraction filters 참고).

인자 filename, extract_dir, format 와 함께 감사 이벤트 shutil.unpack_archive 를 발생시켜요.

경고: 사전 검사 없이 신뢰할 수 없는 출처의 아카이브를 절대 풀지 마세요. extract_dir 인자에 지정된 경로 밖에 파일이 생길 수 있어요. 예를 들어 절대 경로 이름이나 ".." 구성 요소를 가진 파일 이름이 그렇죠.

Python 3.14부터 내장 형식(zip 및 tar 파일) 둘 다의 기본값이 그런 보안 문제 중 가장 위험한 것들을 막아 주지만, 모든 의도하지 않은 동작을 막지는 않아요. tar 특정 세부사항은 Hints for further verification 절을 읽어보세요.

3.7 버전 변경: filenameextract_dir 에 대해 path-like 객체를 받아요.

3.12 버전 변경: filter 인자가 추가됐어요.

shutil.register_unpack_format(*name*, *extensions*, *function*[, *extra_args*[, *description*]])

언팩 형식을 등록해요. name 은 형식의 이름이고 extensions 는 형식에 해당하는 확장자들의 리스트예요(Zip 파일의 .zip 같은).

function 은 아카이브를 푸는 데 쓰일 callable이에요. 이 callable은 다음을 받아요:

  • 아카이브의 경로(위치 인자).
  • 아카이브가 추출돼야 하는 디렉터리(위치 인자).
  • unpack_archive() 에 주어졌다면 filter 키워드 인자.
  • extra_args(name, value) 튜플 시퀀스로 지정한 추가 키워드 인자.

description 을 제공해 형식을 설명할 수 있고, get_unpack_formats() 함수가 반환해요.

shutil.unregister_unpack_format(*name*)

언팩 형식을 해제해요. name 은 형식의 이름이에요.

shutil.get_unpack_formats()

언팩을 위해 등록된 모든 형식의 목록을 반환해요. 반환된 시퀀스의 각 요소는 튜플 (name, extensions, description) 이에요.

기본적으로 shutil 은 다음 형식을 제공해요:

  • zip: ZIP 파일(해당 모듈이 있으면 압축 파일 해제가 동작).
  • tar: 압축되지 않은 tar 파일.
  • gztar: gzip으로 압축된 tar 파일(zlib 모듈이 있으면).
  • bztar: bzip2로 압축된 tar 파일(bz2 모듈이 있으면).
  • xztar: xz로 압축된 tar 파일(lzma 모듈이 있으면).
  • zstdtar: Zstandard로 압축된 tar 파일(compression.zstd 모듈이 있으면).

register_unpack_format() 을 사용해 새 형식을 등록하거나 기존 형식에 자신만의 언패커를 제공할 수 있어요.

아카이빙 예제

이 예제에서는 사용자의 .ssh 디렉터리에서 찾은 모든 파일을 담은 gzip 압축 tar 파일 아카이브를 만들어요:

>>> from shutil import make_archive
>>> import os
>>> archive_name = os.path.expanduser(os.path.join('~', 'myarchive'))
>>> root_dir = os.path.expanduser(os.path.join('~', '.ssh'))
>>> make_archive(archive_name, 'gztar', root_dir)
'/Users/tarek/myarchive.tar.gz'

결과 아카이브는 다음을 포함해요:

$ tar -tzvf /Users/tarek/myarchive.tar.gz
drwx------ tarek/staff       0 2010-02-01 16:23:40 ./
-rw-r--r-- tarek/staff     609 2008-06-09 13:26:54 ./authorized_keys
-rwxr-xr-x tarek/staff      65 2008-06-09 13:26:54 ./config
-rwx------ tarek/staff     668 2008-06-09 13:26:54 ./id_dsa
-rwxr-xr-x tarek/staff     609 2008-06-09 13:26:54 ./id_dsa.pub
-rw------- tarek/staff    1675 2008-06-09 13:26:54 ./id_rsa
-rw-r--r-- tarek/staff     397 2008-06-09 13:26:54 ./id_rsa.pub
-rw-r--r-- tarek/staff   37192 2010-02-06 18:23:10 ./known_hosts

base_dir 을 사용한 아카이빙 예제

이 예제는 위의 예제와 비슷하지만 make_archive()base_dir 와 함께 사용하는 방법을 보여줘요. 이제 다음과 같은 디렉터리 구조가 있다고 해 봐요:

$ tree tmp
tmp
└── root
    └── structure
        ├── content
            └── please_add.txt
        └── do_not_add.txt

최종 아카이브에는 please_add.txt 는 포함돼야 하지만 do_not_add.txt 는 포함되지 않아야 해요. 그래서 다음과 같이 사용해요:

>>> from shutil import make_archive
>>> import os
>>> archive_name = os.path.expanduser(os.path.join('~', 'myarchive'))
>>> make_archive(
...     archive_name,
...     'tar',
...     root_dir='tmp/root',
...     base_dir='structure/content',
... )
'/Users/tarek/myarchive.tar'

결과 아카이브의 파일을 나열하면:

$ python -m tarfile -l /Users/tarek/myarchive.tar
structure/content/
structure/content/please_add.txt

출력 터미널 크기 조회

shutil.get_terminal_size(*fallback=(columns, lines)*)

터미널 창의 크기를 가져와요.

두 차원 각각에 대해 환경 변수 COLUMNSLINES 가 각각 확인돼요. 변수가 정의돼 있고 값이 양의 정수라면 그것이 사용돼요.

COLUMNSLINES 가 정의되지 않은 일반적인 경우라면, sys.__stdout__ 에 연결된 터미널이 os.get_terminal_size() 를 호출해 조회돼요.

터미널 크기를 성공적으로 조회할 수 없으면(시스템이 조회를 지원하지 않거나 터미널에 연결돼 있지 않은 경우), fallback 매개변수에 주어진 값이 사용돼요. fallback 은 기본적으로 (80, 24) 로, 많은 터미널 에뮬레이터가 쓰는 기본 크기예요.

반환 값은 os.terminal_size 형식의 named tuple이에요.

참고: Single UNIX Specification, Version 2의 Other Environment Variables 도 참고하세요.

3.3 버전에서 추가.

3.11 버전 변경: os.get_terminal_size() 가 0을 반환하면 fallback 값도 사용돼요.

더 알아보기

  • os — 개별 파일에 대한 저수준 연산.
  • zipfile, tarfile — 아카이브 연산의 기반이 되는 모듈.