You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python获取一级子目录按最后访问时间倒序及磁盘清理需求

Hey there! Let's walk through building this disk cleanup function step by step—since you're new to Python, I'll keep things clear and add plenty of notes so you understand what's going on.

Step 1: Get Top-Level Subdirectories Efficiently

Instead of using os.listdir() (which only returns filenames), we'll use os.scandir(). It's faster because it grabs file metadata (like access times) right away, so we don't have to make extra calls to fetch that info later. We'll filter out files and symlinks to keep only actual directories.

Step 2: Sort by Last Access Time

Each entry from os.scandir() has a .stat() method that gives us access to st_atime—the timestamp of the last time the directory was accessed. We'll use Python's sorted() function to sort these directories: for disk cleanup, we usually delete the least recently accessed (oldest) first, so we'll sort in ascending order. If you want to delete newest first instead, just flip the reverse flag.

Step 3: Calculate Directory Size

To know how much space deleting a directory will free up, we need a helper function to recursively calculate the total size of all files and subdirectories inside it. We'll add error handling here for cases where we don't have permission to access parts of the directory.

Step 4: The Cleanup Logic

We'll loop through our sorted directories, delete them one by one, and keep track of how much space we've freed until we hit our target MB count. We'll handle common errors like permission issues or missing directories so the function doesn't crash unexpectedly.

Full Working Code

import os
import shutil

def get_dir_size(path):
    """Recursively calculate the total size of a directory in bytes"""
    total_size = 0
    try:
        # Use scandir for efficiency here too
        for entry in os.scandir(path):
            if entry.is_file(follow_symlinks=False):
                # Add file size directly
                total_size += entry.stat(follow_symlinks=False).st_size
            elif entry.is_dir(follow_symlinks=False):
                # Recursively calculate subdirectory size
                total_size += get_dir_size(entry.path)
    except PermissionError:
        print(f"Warning: No permission to access {path} — skipping this directory.")
    return total_size

def disk_cleanup(target_dir, mb_to_free):
    """
    Clean up directories in target_dir to free up specified MB.
    Sorts top-level subdirectories by last access time (oldest first gets deleted).
    """
    # Convert MB to bytes (since all file size functions use bytes)
    bytes_to_free = mb_to_free * 1024 * 1024
    freed_bytes = 0

    # Get all entries in the target directory
    try:
        entries = os.scandir(target_dir)
    except FileNotFoundError:
        print(f"Error: Target directory '{target_dir}' doesn't exist.")
        return
    except PermissionError:
        print(f"Error: You don't have permission to access '{target_dir}'.")
        return

    # Filter to keep only top-level directories (skip files and symlinks)
    subdirs = [entry for entry in entries if entry.is_dir(follow_symlinks=False)]

    # Sort directories by last access time: oldest first (delete least used first)
    # Change reverse=True if you want to delete newest first instead
    sorted_subdirs = sorted(subdirs, key=lambda x: x.stat().st_atime, reverse=False)

    print(f"Found {len(sorted_subdirs)} top-level directories.")
    print(f"Target: Free up {mb_to_free} MB ({bytes_to_free:,} bytes).")

    # Iterate through sorted directories and delete until we hit the target
    for dir_entry in sorted_subdirs:
        if freed_bytes >= bytes_to_free:
            break  # We've freed enough space, stop here

        dir_path = dir_entry.path
        dir_size_bytes = get_dir_size(dir_path)
        dir_size_mb = dir_size_bytes / 1024 / 1024

        # Print some info for transparency
        print(f"\nProcessing: {dir_path}")
        print(f"Size: {dir_size_mb:.2f} MB | Last accessed: {os.path.getatime(dir_path)}")

        try:
            # Delete the entire directory tree
            shutil.rmtree(dir_path)
            freed_bytes += dir_size_bytes
            print(f"Deleted! Total freed so far: {freed_bytes / 1024 / 1024:.2f} MB")
        except PermissionError:
            print(f"Warning: Can't delete {dir_path} — permission denied. Skipping.")
        except Exception as e:
            print(f"Error deleting {dir_path}: {str(e)}. Skipping.")

    # Final status update
    if freed_bytes >= bytes_to_free:
        print(f"\n✅ Success! Freed {freed_bytes / 1024 / 1024:.2f} MB, which meets your target of {mb_to_free} MB.")
    else:
        print(f"\n⚠️ Warning: Only freed {freed_bytes / 1024 / 1024:.2f} MB. Couldn't reach the target — no more directories to delete.")

# Example usage (test with a dummy directory first!):
# disk_cleanup("/path/to/your/test/directory", 500)  # Free up 500 MB

Key Notes for You (As a Python Newbie)

  • os.scandir() vs os.listdir(): scandir is more efficient because it caches metadata, which saves us from calling os.stat() on every entry separately.
  • Error Handling: We added catches for PermissionError and FileNotFoundError so the function doesn't crash if it runs into issues—super important for scripts that modify files/directories.
  • Unit Conversion: All file size functions in Python use bytes, so we convert MB to bytes by multiplying by 1024 * 1024 (since 1 MB = 1024 KB, 1 KB = 1024 bytes).
  • Testing: Always test with a dummy directory first! Create a folder with test subdirectories and files to verify the function works before using it on important data.

内容的提问来源于stack exchange,提问作者chross

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 07:34:15