87 lines
2.9 KiB
Python
87 lines
2.9 KiB
Python
import os
|
|
import sys
|
|
|
|
def get_size_format(b, factor=1024, suffix="B"):
|
|
"""
|
|
将字节大小转换为更易读的格式 (KB, MB, GB, 等)
|
|
"""
|
|
for unit in ["", "K", "M", "G", "T", "P", "E", "Z"]:
|
|
if b < factor:
|
|
return f"{b:.2f} {unit}{suffix}"
|
|
b /= factor
|
|
return f"{b:.2f} Y{suffix}"
|
|
|
|
def get_directory_size(directory):
|
|
"""
|
|
递归获取文件夹总大小(字节)
|
|
使用 os.scandir 比 os.walk 更快
|
|
"""
|
|
total = 0
|
|
try:
|
|
for entry in os.scandir(directory):
|
|
if entry.is_file(follow_symlinks=False):
|
|
total += entry.stat(follow_symlinks=False).st_size
|
|
elif entry.is_dir(follow_symlinks=False):
|
|
total += get_directory_size(entry.path)
|
|
except PermissionError:
|
|
# 跳过无权限访问的文件夹/文件
|
|
pass
|
|
except FileNotFoundError:
|
|
pass
|
|
except Exception:
|
|
pass
|
|
return total
|
|
|
|
def scan_folders(target_dir):
|
|
"""
|
|
扫描目标目录下的子文件夹和文件,并按大小降序输出
|
|
"""
|
|
print(f"开始扫描目录: {target_dir}\n")
|
|
if not os.path.exists(target_dir):
|
|
print(f"路径不存在: {target_dir}")
|
|
return
|
|
|
|
items_sizes = []
|
|
|
|
try:
|
|
for entry in os.scandir(target_dir):
|
|
if entry.is_dir(follow_symlinks=False):
|
|
size = get_directory_size(entry.path)
|
|
items_sizes.append({'name': entry.name, 'size': size, 'path': entry.path, 'type': '文件夹'})
|
|
elif entry.is_file(follow_symlinks=False):
|
|
size = entry.stat(follow_symlinks=False).st_size
|
|
items_sizes.append({'name': entry.name, 'size': size, 'path': entry.path, 'type': '文件'})
|
|
except PermissionError:
|
|
print(f"警告: 没有权限访问目录 '{target_dir}'。")
|
|
return
|
|
|
|
# 按大小降序排序
|
|
items_sizes.sort(key=lambda x: x['size'], reverse=True)
|
|
|
|
# 打印结果表头
|
|
# 由于中文宽度问题,简单格式化可能无法完美对齐,这里尽量保证可读性
|
|
print(f"{'类型':<5} | {'大小':<12} | {'名称'}")
|
|
print("-" * 60)
|
|
|
|
total_size = 0
|
|
for item in items_sizes:
|
|
size_str = get_size_format(item['size'])
|
|
print(f"{item['type']:<5} | {size_str:<12} | {item['name']}")
|
|
total_size += item['size']
|
|
|
|
print("-" * 60)
|
|
print(f"当前目录总大小: {get_size_format(total_size)}")
|
|
|
|
if __name__ == "__main__":
|
|
# 如果通过命令行传入参数,则使用参数作为路径,否则提示用户输入或默认扫描当前目录
|
|
if len(sys.argv) > 1:
|
|
target = sys.argv[1]
|
|
else:
|
|
target = input("请输入要扫描的文件夹路径 (按回车扫描当前目录): ").strip()
|
|
if not target:
|
|
target = "."
|
|
|
|
# 获取绝对路径并执行扫描
|
|
target_abs = os.path.abspath(target)
|
|
scan_folders(target_abs)
|