- shutil은 파일/디렉토리를 다루는 고수준 표준 라이브러리
- 저수준인 os보다 간편함
- 내부적으로 os를 사용함. os 감싸서 편하게 만든 것
copy
import shutil
from pathlib import Path
print(Path('foo.txt').read_text())
shutil.copy('bar.txt', 'foo.txt')
print(Path('foo.txt').read_text())
this is foo
this is bar
- copy(src, dst)
- src 파일을 dst 경로로 복사
- dst가 존재하는 파일이면 덮어씀
- dst가 디렉토리면 해당 디렉토리 안에 동일한 파일명으로 복사됨
- 내용 + 권한만 복사
Copy2
import shutil
from pathlib import Path
import os
print(Path('foo.txt').read_text())
shutil.copy2('bar.txt', 'foo.txt')
print(Path('foo.txt').read_text())
bar_stat = os.stat('bar.txt')
print(bar_stat.st_mtime)
foo_stat = os.stat('foo.txt')
print(foo_stat.st_mtime)
this is bar
this is bar
1774984482.7004178
1774984482.7004178
- copy2(src, dst)
- copy2는 내용 + 권한 + 메타데이터까지 복사(수정 시간, 접근 시간 등 stat 정보 포함)
- dst가 존재하는 파일이면 덮어씀
copyfile
import shutil
shutil.copyfile('bar.txt', 'foo.txt')
- 파일 내용만 복사
- 디렉토리에는 사용 불가
- src와 dst는 반드시 파일이어야 함
- 권한, 메타데이터는 복사x
- dst가 존재하면 덮어씀
copytree
import shutil
import os
shutil.copytree('./temp', './temp_copy')
print(os.listdir('./temp'))
print(os.listdir('./temp_copy'))
['bar.txt', 'foo.txt']
['bar.txt', 'foo.txt']
import shutil
shutil.copytree('src', 'dst')
FileExistsError: [WinError 183] 파일이 이미 있으므로 만들 수 없습니다: 'dst'
- 경로가 이미 존재하면 FileExistsError에러가 발생
import shutil
import os
print(os.listdir('dst'))
shutil.copytree('src', 'dst', dirs_exist_ok=True)
print(os.listdir('dst'))
[]
['foo.txt']
- dirs_exist_ok=True 옵션으로 dst 폴더가 있어도 에러없이 복사 가능
- 기존 파일은 덮어쓰고 없는 파일만 추가됨(merge 방식)
- dst에만 존재하는 파일은 삭제X
import shutil
import os
print(os.listdir('./temp'))
shutil.copytree('./temp', 'temp_copy', ignore=shutil.ignore_patterns('*.txt'))
print(os.listdir('temp_copy'))
['bar.txt', 'README.md']
['README.md']
- ignore=shutil.ignore_patterns는 glob 패턴 기반으로 제외할 파일 지정 (*.txt 등)
move
import shutil
import os
print(os.listdir('.'))
shutil.move('./temp/foo.txt', './foo.txt')
print(os.listdir('.'))
['app.py', 'main.py', 'temp']
['app.py', 'foo.txt', 'main.py', 'temp']
import shutil
import os
print(os.listdir('.'))
shutil.move('foo.txt', 'bar.txt')
print(os.listdir('.'))
['app.py', 'foo.txt', 'main.py', 'temp']
['app.py', 'bar.txt', 'main.py', 'temp']
- 이름 변경도 가능
- 같은 파일 시스템에서는 rename으로 동작(빠름)
- 다른 파일 시스템에서는 copy + delete로 동작(느림)
rmtree
import shutil
shutil.rmtree('temp')
make_archive
import shutil
import os
shutil.make_archive('backup', 'zip', 'temp')
print(os.listdir('.'))
['app.py', 'backup.zip', 'main.py', 'temp']
- shutil.make_archive(base_name, format, root_dir, base_dir)
- base_name: 압축 파일 경로 + 이름(확장자 제외)
- format: zip, tar, gztar 등 다양한 포맷 지원
import shutil
shutil.make_archive('a', 'zip', base_dir='temp')
import shutil
shutil.make_archive('a', 'zip', root_dir='temp', base_dir='.')
- temp폴더를 제외한 temp폴더내의 요소들만 압축
unpack_archive
import shutil
import os
shutil.unpack_archive('backup.zip', 'unpack_folder')
print(os.listdir('.'))
['app.py', 'backup.zip', 'main.py', 'temp', 'unpack_folder']
disk_usage
import shutil
total, used, free = shutil.disk_usage('.')
print(total)
print(used)
print(free)
1022992248832
720493629440
302498619392
- 디스크 저장 공간 체크
- total, used, free 순으로 받음
- 바이트단위