← Back to Chapters

Python shutil Module

? Python shutil Module

⚡ Quick Overview

The shutil (shell utilities) module in Python provides high-level functions for working with files, directories, and archives. It builds on top of the lower-level os module and makes common tasks like copying, moving, deleting folders, and creating backups much simpler and safer.

Use shutil whenever you need to:

  • Copy files or entire directory trees.
  • Move or rename files and folders.
  • Delete non-empty directories.
  • Create or extract compressed archives (zip, tar, etc.).
  • Check disk usage statistics.

? Key Concepts

  • High-level operations: Functions like copy(), copytree(), move(), rmtree() abstract away OS-specific details.
  • File vs directory operations: Some functions work on files only, some on directories, and some on both.
  • Metadata handling: copy() vs copy2() differ in whether they also copy metadata (timestamps, permissions).
  • Recursive behaviour: copytree() and rmtree() recursively process directories.
  • Archive utilities: make_archive() and unpack_archive() help create and extract compressed backups.
  • Disk usage: disk_usage() gives total, used, and free space for a given path.

? Syntax and Important Functions

? Copying Files and Directories

  • shutil.copyfile(src, dst) – copy contents of one file to another.
  • shutil.copy(src, dst) – copy file + permissions.
  • shutil.copy2(src, dst) – copy file + metadata (timestamps, etc.).
  • shutil.copytree(src, dst, dirs_exist_ok=False) – recursively copy an entire directory tree.

? Moving and Deleting

  • shutil.move(src, dst) – move or rename files/directories.
  • shutil.rmtree(path) – delete a directory tree (even if not empty).

?️ Working with Archives

  • shutil.make_archive(base_name, format, root_dir)
    Creates an archive (zip, tar, etc.) from a directory.
  • shutil.unpack_archive(filename, extract_dir=None)
    Extracts an archive to a directory.

? Disk Usage

  • shutil.disk_usage(path)
    Returns a tuple: (total, used, free) bytes.

? Code Examples

? Copy a file and preserve metadata
import shutil
from pathlib import Path

source = Path("data/report.txt")
destination = Path("backup/report.txt")

# Ensure parent directory exists
destination.parent.mkdir(parents=True, exist_ok=True)

# copy2 copies file contents + metadata (timestamps, permissions)
shutil.copy2(source, destination)

print("Backup created at:", destination)
? Copy an entire project folder
import shutil

src_dir = "project_v1"
dst_dir = "project_backup"

# Copy entire directory tree recursively
# dirs_exist_ok=True (Python 3.8+) allows destination to exist
shutil.copytree(src_dir, dst_dir, dirs_exist_ok=True)

print("Project copied to:", dst_dir)
?️ Create a ZIP archive backup
import shutil

# base_name: path without extension
# format: "zip", "tar", "gztar", "bztar", "xztar"
# root_dir: directory to archive
archive_path = shutil.make_archive(
    base_name="backups/source_code_backup",
    format="zip",
    root_dir="src"
)

print("Archive created at:", archive_path)
? Check disk usage of a drive
import shutil

# Get disk usage statistics for the root directory
usage = shutil.disk_usage("/")

# Convert byte values to gigabytes for easier reading
total_gb = usage.total / (1024 ** 3)
used_gb = usage.used / (1024 ** 3)
free_gb = usage.free / (1024 ** 3)

# Print a simple disk space report
print(f"Total: {total_gb:.2f} GB")
print(f"Used : {used_gb:.2f} GB")
print(f"Free : {free_gb:.2f} GB")

? Live Output / Explanation

What happens in the copy + backup examples?

  1. Copying a file with copy2():
    • The destination folder (backup/) is created if it does not exist.
    • copy2() copies the file contents and metadata.
    • The printed path confirms where the backup is stored.
  2. Copying an entire folder with copytree():
    • All subfolders and files from project_v1 are copied to project_backup.
    • If dirs_exist_ok=True, the destination can already exist (Python 3.8+).
    • Useful for making snapshots of your project.
  3. Creating an archive with make_archive():
    • The src folder is compressed into a ZIP file named source_code_backup.zip inside backups/.
    • The returned archive_path tells you exactly where the zip is stored.
  4. Checking disk usage with disk_usage():
    • Returns total, used, and free space in bytes.
    • Converting to GB makes it easier to read and display.

✅ Safe and Efficient Use of shutil

  • Always check paths before copying/moving to avoid overwriting important data.
  • Use pathlib.Path with shutil for cleaner, cross-platform path handling.
  • Prefer copy2() over copy() when metadata matters (e.g., backups, logs).
  • Be careful with rmtree() – it permanently deletes directories (including contents).
  • Log what you are copying/moving in larger scripts so you can debug issues later.
  • Use try/except around file operations to handle missing files or permission errors.

? Practice Tasks Using shutil

  1. Create a daily backup script:
    Write a Python script that copies a folder called important_docs into a backups/ folder with the current date in the folder name.
  2. Project snapshot:
    Use copytree() to create a snapshot of your current coding project before you start a risky refactor.
  3. Auto-archive logs:
    Compress a logs/ folder into a ZIP file at the end of each day using make_archive().
  4. Disk space checker:
    Build a small script that warns you (prints a message) if free disk space is less than 10 GB using disk_usage().
  5. Safe cleanup tool:
    Create a script that deletes a temporary folder using rmtree(), but only after asking for confirmation in the terminal.

You can run these scripts from the command line with: python your_script_name.py

? Common Use Cases

  • Automated backups of projects, documents, and configuration files.
  • Deployment scripts that prepare folders and move files into place.
  • Cleaning up temporary build artifacts or cache directories.
  • Packaging source code or datasets into archives to share or upload.
  • Monitoring disk usage on servers or local machines.