Module os trong Python cung cấp các thao tác cơ bản với hệ thống tập tin như tạo, xóa, và truy vấn thuộc tính. Tuy nhiên, khi cần thực hiện các tác vụ phức tạp hơn như sao chép, di chuyển, nén hoặc giải nén thư mục, os tỏ ra hạn chế. Để giải quyết vấn đề này, Python cung cấp module shutil (shell utilities), một công cụ mạnh mẽ cho các thao tác tập tin và thư mục ở cấp độ cao.
Sao chép nội dung tập tin
Hàm copyfileobj cho phép sao chép dữ liệu từ một đối tượng tập tin nguồn sang đối tượng tập tin đích. Bạn có thể chỉ định kích thước bộ đệm (buffer) để tối ưu hóa hiệu suất khi xử lý các tập tin lớn.
import shutil
# Sử dụng context manager để tự động đóng tập tin
with open('source_data.json', 'r', encoding='utf-8') as src_file, \
open('dest_data.json', 'w', encoding='utf-8') as dst_file:
# Sao chép với buffer 8KB
shutil.copyfileobj(src_file, dst_file, length=8192)
Nếu bạn chỉ có đường dẫn tập tin thay vì đối tượng tập tin đã mở, copyfile là lựa chọn phù hợp. Hàm này sẽ tự động tạo tập tin đích nếu nó chưa tồn tại.
import shutil
shutil.copyfile('reports/daily_log.txt', 'backups/daily_log_backup.txt')
Sao chép quyền hạn và siêu dữ liệu
shutil cung cấp nhiều cấp độ sao chép siêu dữ liệu (metadata) và quyền truy cập:
copymode: Chỉ sao chép quyền truy cập (permissions). Tập tin đích phải tồn tại trước.copystat: Sao chép các thông tin trạng thái như thời gian truy cập, thời gian chỉnh sửa và các cờ (flags). Tập tin đích phải tồn tại trước.copy: Sao chép nội dung tập tin và quyền truy cập (tương đươngcopyfile+copymode).copy2: Sao chép nội dung tập tin và toàn bộ siêu dữ liệu (tương đươngcopyfile+copystat).
import shutil
# Sao chép nội dung và quyền hạn
shutil.copy('scripts/deploy.sh', '/usr/local/bin/deploy.sh')
# Sao chép nội dung và toàn bộ metadata (thời gian tạo, sửa đổi...)
shutil.copy2('configs/app_settings.yaml', 'configs/app_settings_prod.yaml')
Thao tác với thư mục: Sao chép, Xóa và Di chuyển
Để sao chép toàn bộ cây thư mục, sử dụng copytree. Hàm này cho phép bỏ qua một số tập tin hoặc thư mục cụ thể thông qua tham số ignore.
import shutil
# Bỏ qua các tập tin tạm và log khi sao chép thư mục dự án
ignore_func = shutil.ignore_patterns('*.tmp', '*.log', '__pycache__')
shutil.copytree(
src='projects/web_app',
dst='backups/web_app_backup',
ignore=ignore_func,
dirs_exist_ok=True # Cho phép ghi đè nếu thư mục đích đã tồn tại (Python 3.8+)
)
Để xóa đệ quy một thư mục và toàn bộ nội dung bên trong, sử dụng rmtree. Để di chuyển tập tin hoặc thư mục, sử dụng move.
import shutil
# Di chuyển thư mục cũ sang vị trí lưu trữ
shutil.move('logs/2022_archive', 'storage/old_logs/2022_archive')
# Xóa sạch thư mục tạm
shutil.rmtree('temp/build_files')
Nén và Giải nén tập tin
make_archive giúp tạo các tệp nén (như zip, tar, gztar) một cách nhanh chóng và trả về đường dẫn đến tệp nén đã tạo.
import shutil
# Nén thư mục 'dataset' thành file 'dataset_backup.tar.gz' và lưu vào '/tmp'
archive_path = shutil.make_archive(
base_name='/tmp/dataset_backup',
format='gztar',
root_dir='data/dataset'
)
print(f"Đã tạo file nén tại: {archive_path}")
Đối với việc giải nén, shutil không cung cấp hàm trực tiếp cho mọi định dạng, nhưng bạn có thể kết hợp với module zipfile hoặc tarfile có sẵn trong thư viện chuẩn để xử lý.
import zipfile
import os
archive_file = 'releases/v1.0.4.zip'
extract_dir = 'deploy/v1.0.4'
# Đảm bảo thư mục giải nén tồn tại
os.makedirs(extract_dir, exist_ok=True)
with zipfile.ZipFile(archive_file, 'r') as zip_ref:
# Giải nén toàn bộ nội dung
zip_ref.extractall(extract_dir)