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

如何用Python检测Windows上的按需下载(稀疏)文件?

如何用Python检测Windows上的按需下载(稀疏)文件?

嗨Vladimir,你碰到的这种文件其实是Windows里的稀疏文件——Dropbox的按需下载功能就是用这种机制:文件目录里显示的是完整的逻辑大小,但实际磁盘上只存储了已经下载的部分。当你卸载Dropbox后,这些文件就只剩占位标记,实际磁盘占用为0字节。

你提到用os.path.getsize()或os.stat()只能拿到逻辑大小,这很正常,因为这些Python标准库函数返回的是文件“应该有”的大小,不是实际在磁盘上占的空间。要获取真实的磁盘占用,我们需要调用Windows系统API,这里给你两种可行的方案:


方法一:使用pywin32库(简单易读)

pywin32是专门用于Windows系统交互的Python库,能方便调用各类Windows API。

步骤1:安装pywin32

先通过pip安装库:

pip install pywin32

步骤2:编写检测函数

这个函数会获取文件实际在磁盘上分配的空间(也就是你在属性里看到的“Size on disk”):

import win32file
from win32file import FILE_STANDARD_INFO

def get_size_on_disk(file_path):
    try:
        # 打开文件获取句柄
        handle = win32file.CreateFile(
            file_path,
            win32file.GENERIC_READ,
            win32file.FILE_SHARE_READ | win32file.FILE_SHARE_WRITE,
            None,
            win32file.OPEN_EXISTING,
            0,
            None
        )
        # 获取文件标准信息,其中包含实际磁盘分配大小
        file_info = win32file.GetFileInformationByHandleEx(handle, FILE_STANDARD_INFO)
        win32file.CloseHandle(handle)
        # 返回实际占用的字节数
        return file_info['AllocationSize']
    except Exception as e:
        print(f"处理文件 {file_path} 时出错: {e}")
        return -1

方法二:使用ctypes(无需额外安装库)

如果你不想装第三方库,可以用Python内置的ctypes直接调用Windows内核API,实现同样的功能:

import ctypes
from ctypes import wintypes

# 加载Windows内核库
kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)

# 定义存储文件标准信息的结构
class FILE_STANDARD_INFO(ctypes.Structure):
    _fields_ = [
        ('AllocationSize', wintypes.LARGE_INTEGER),
        ('EndOfFile', wintypes.LARGE_INTEGER),
        ('NumberOfLinks', wintypes.DWORD),
        ('DeletePending', wintypes.BOOL),
        ('Directory', wintypes.BOOL)
    ]

# 定义API函数的参数和返回值类型
kernel32.CreateFileW.argtypes = [
    wintypes.LPCWSTR, wintypes.DWORD, wintypes.DWORD, wintypes.LPVOID,
    wintypes.DWORD, wintypes.DWORD, wintypes.HANDLE
]
kernel32.CreateFileW.restype = wintypes.HANDLE

kernel32.GetFileInformationByHandleEx.argtypes = [
    wintypes.HANDLE, wintypes.DWORD, wintypes.LPVOID, wintypes.DWORD
]
kernel32.GetFileInformationByHandleEx.restype = wintypes.BOOL

kernel32.CloseHandle.argtypes = [wintypes.HANDLE]
kernel32.CloseHandle.restype = wintypes.BOOL

def get_size_on_disk_ctypes(file_path):
    # 打开文件
    handle = kernel32.CreateFileW(
        file_path,
        0x80000000,  # GENERIC_READ
        0x00000001 | 0x00000002,  # FILE_SHARE_READ | FILE_SHARE_WRITE
        None,
        3,  # OPEN_EXISTING
        0x80,  # FILE_ATTRIBUTE_NORMAL
        None
    )
    if handle == wintypes.HANDLE(-1).value:
        raise ctypes.WinError(ctypes.get_last_error())
    
    try:
        # 获取文件实际占用信息
        file_info = FILE_STANDARD_INFO()
        buf_size = ctypes.sizeof(file_info)
        if not kernel32.GetFileInformationByHandleEx(
            handle, 0,  # 0对应FileStandardInfo类型
            ctypes.byref(file_info), buf_size
        ):
            raise ctypes.WinError(ctypes.get_last_error())
        # 返回实际磁盘占用字节数
        return file_info.AllocationSize.QuadPart
    finally:
        # 确保关闭文件句柄
        kernel32.CloseHandle(handle)

批量检测并删除目标文件

有了上面的检测函数,你可以遍历目标文件夹,找出所有实际磁盘占用为0的文件并删除:

import os

def clean_zero_disk_space_files(target_folder):
    for root, _, files in os.walk(target_folder):
        for filename in files:
            file_path = os.path.join(root, filename)
            try:
                # 这里可以替换成你用的函数:get_size_on_disk 或 get_size_on_disk_ctypes
                disk_size = get_size_on_disk_ctypes(file_path)
                if disk_size == 0:
                    print(f"即将删除: {file_path}")
                    # os.remove(file_path)  # 测试确认后再取消注释这行
            except Exception as e:
                print(f"跳过文件 {file_path}: {e}")

# 替换成你要清理的文件夹路径
clean_zero_disk_space_files(r"C:\Your\Dropbox\遗留文件夹路径")

注意事项

  1. 先测试再删除:建议先保留os.remove的注释,只打印文件路径,确认都是你要删除的Dropbox占位文件后再执行删除操作。
  2. 权限问题:如果目标文件夹在系统保护目录(比如C:\Program Files),可能需要以管理员身份运行Python脚本。

备注:内容来源于stack exchange,提问作者Vladimir Buzalka

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.13 20:23:07