
File Cleaner
- 33 installs
- 82 repo stars
- Updated August 2, 2026
- aaaaqwq/claude-code-skills
file-cleaner is a Claude Code skill that scans directories for large and junk files and cleans them interactively to free disk space.
About
file-cleaner is a Claude Code skill that scans directories for large files and junk files such as temp files, caches, logs, and build artifacts. It offers an interactive cleanup interface, a dry-run mode, and a generated cleanup script. A developer uses it to reclaim disk space and clear build and cache clutter from projects. It auto-excludes system, version-control, and Python environment directories to avoid deleting important files.
- Scans directories for large files and 7 categories of junk files
- Interactive cleanup with dry-run mode and generated cleanup scripts
- Auto-excludes system, version-control, and Python-env directories
File Cleaner by the numbers
- 33 all-time installs (skills.sh)
- Ranked #341 of 550 CLI & Terminal skills by installs in the Skillselion catalog
- Data as of Aug 3, 2026 (Skillselion catalog sync)
file-cleaner capabilities & compatibility
Free; only Python 3 is required, no API keys.
- Capabilities
- disk cleanup · large file scan · junk file scan · interactive delete
- Use cases
- devops
- Platforms
- macOS · Linux
- Pricing
- Free
What file-cleaner says it does
系统文件清理工具。扫描和识别大文件、垃圾文件(临时文件、缓存、日志、备份等),提供交互式清理界面让用户选择删除。
识别 7 种垃圾文件类型,分类统计,标记安全删除状态。可生成自动清理脚本。
npx skills add https://github.com/aaaaqwq/claude-code-skills --skill file-cleanerAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 33 |
|---|---|
| repo stars | ★ 82 |
| Last updated | August 2, 2026 |
| Repository | aaaaqwq/claude-code-skills ↗ |
What it does
A developer reclaims disk space by scanning for large and junk files and interactively deleting them with a dry-run safety net.
Who is it for?
Developers reclaiming disk space by clearing caches, build artifacts, temp files, and large files.
Skip if: Recovering deleted files, since deletion is irreversible and the docs recommend using trash instead.
When should I use this skill?
When you need to clean disk space, find large files, or delete junk files and build artifacts.
What you get
A reviewed, dry-runnable cleanup that removes junk and large files while excluding protected directories.
- Large-file and junk-file scan reports
- Interactive cleanup or generated cleanup script
By the numbers
- 7 junk-file categories detected
- Default large-file threshold of 10MB
- 3 cleanup scripts (find_large_files, find_garbage, clean_interactive)
Files
File Cleaner
系统文件清理工具,帮助用户扫描、识别和清理大文件与垃圾文件。
核心功能
1. 大文件扫描
扫描指定目录,找出占用空间的大文件(默认 >10MB)。
python3 scripts/find_large_files.py <directory> [options]选项:
--min-size <MB>- 最小文件大小(默认: 10)--max-results <N>- 最大结果数(默认: 100)--show <N>- 显示的文件数(默认: 20)--export <path>- 导出结果到 JSON
示例:
# 扫描 home 目录的大文件
python3 scripts/find_large_files.py ~
# 扫描大于 50MB 的文件
python3 scripts/find_large_files.py ~ --min-size 50
# 导出结果
python3 scripts/find_large_files.py ~ --export large_files.json2. 垃圾文件扫描
扫描并识别各类垃圾文件:临时文件、缓存、日志、备份等。
python3 scripts/find_garbage.py <directory> [options]垃圾文件类别:
temp_files- 临时文件(.tmp, .temp, .bak, .swp, .DS_Store)cache_files- 缓存文件(__pycache__, *.pyc, .cache)log_files- 日志文件(*.log)backup_files- 备份文件(.backup, .old)build_artifacts- 构建产物(dist, build, .next, out)editor_temp- 编辑器临时文件(.swo, .swn)download_temp- 下载临时文件(.crdownload, .part)
选项:
--categories <cat1> <cat2>- 指定扫描类别(默认: 全部)--show <N>- 每个类别显示的文件数(默认: 10)--export <path>- 导出结果到 JSON--script <path>- 生成清理脚本
示例:
# 扫描所有垃圾文件
python3 scripts/find_garbage.py ~
# 只扫描缓存和临时文件
python3 scripts/find_garbage.py ~ --categories cache_files temp_files
# 导出结果
python3 scripts/find_garbage.py ~ --export garbage_scan.json
# 生成清理脚本
python3 scripts/find_garbage.py ~ --script cleanup.sh3. 交互式清理
基于扫描结果,提供交互式界面让用户选择要清理的文件。
python3 scripts/clean_interactive.py <scan_result.json> [options]选项:
--type <garbage|large>- 扫描结果类型(默认: garbage)--dry-run- 预演模式,不实际删除文件
示例:
# 清理垃圾文件
python3 scripts/clean_interactive.py garbage_scan.json
# 清理大文件
python3 scripts/clean_interactive.py large_files.json --type large
# 预演模式(测试)
python3 scripts/clean_interactive.py garbage_scan.json --dry-run工作流程
标准流程:扫描 → 导出 → 清理
# 步骤 1: 扫描垃圾文件
python3 scripts/find_garbage.py ~ --export /tmp/garbage_scan.json
# 步骤 2: 交互式清理
python3 scripts/clean_interactive.py /tmp/garbage_scan.json快速流程:直接清理(推荐)
对于垃圾文件,可以直接生成清理脚本:
# 生成清理脚本
python3 scripts/find_garbage.py ~ --script cleanup.sh
# 检查脚本(确认要删除的文件)
cat cleanup.sh
# 执行清理
bash cleanup.sh大文件流程:分析 → 选择性清理
对于大文件,推荐使用交互式清理:
# 扫描大文件
python3 scripts/find_large_files.py ~ --export /tmp/large_files.json
# 交互式选择删除
python3 scripts/clean_interactive.py /tmp/large_files.json --type large安全特性
自动排除
以下目录和文件会自动排除,避免误删:
- 系统目录:
/proc,/sys,/dev,/usr,/bin等 - 版本控制:
.git,.svn,.hg - Python 环境:
venv,.venv,env
垃圾文件分类
垃圾文件分为两类:
🟢 安全删除(自动标记):
- 临时文件
- 缓存文件
- 备份文件
- 构建产物
- 编辑器临时文件
🟡 需要确认(需手动检查):
- 日志文件(可能用于调试)
- 下载临时文件(可能未完成)
预演模式
使用 --dry-run 测试清理操作,不实际删除:
python3 scripts/clean_interactive.py scan.json --dry-run使用建议
定期清理
建议每月执行一次文件清理:
# 每月清理脚本
python3 scripts/find_garbage.py ~ --export /tmp/monthly_scan.json
python3 scripts/clean_interactive.py /tmp/monthly_scan.json磁盘空间不足
当磁盘空间不足时:
# 1. 找出最大的文件
python3 scripts/find_large_files.py ~ --min-size 100 --show 20
# 2. 清理垃圾文件
python3 scripts/find_garbage.py ~ --script cleanup.sh
bash cleanup.sh项目清理
清理开发项目目录:
# 清理构建产物和缓存
python3 scripts/find_garbage.py ~/projects \
--categories build_artifacts cache_files \
--script project_cleanup.sh注意事项
⚠️ 使用前必读:
1. 先预览再删除
- 使用
--dry-run测试 - 查看扫描结果后再确认
2. 重要文件备份
- 删除前备份重要数据
- 日志文件可能包含重要信息
3. 权限问题
- 某些文件可能需要 sudo 权限
- 无权限的文件会自动跳过
4. 不可恢复
- 删除操作不可撤销
- 建议使用
trash命令而不是直接删除
脚本说明
find_large_files.py
扫描大文件,输出文件列表和总大小。自动排除系统目录和版本控制目录。
find_garbage.py
识别 7 种垃圾文件类型,分类统计,标记安全删除状态。可生成自动清理脚本。
clean_interactive.py
交互式清理界面,支持按类别选择、批量操作、预演模式。显示文件详情和总大小。
示例场景
场景 1:磁盘空间告急
# 快速找出大文件
python3 scripts/find_large_files.py ~ --min-size 500 --show 10场景 2:开发环境清理
# 清理所有构建产物
python3 scripts/find_garbage.py ~/projects \
--categories build_artifacts cache_files \
--export dev_cleanup.json
python3 scripts/clean_interactive.py dev_cleanup.json场景 3:定期维护
# 完整扫描
python3 scripts/find_garbage.py ~ --export monthly_scan.json
python3 scripts/find_large_files.py ~ --export large_files.json
# 分别处理
python3 scripts/clean_interactive.py monthly_scan.json
python3 scripts/clean_interactive.py large_files.json --type large故障排除
权限错误
# 使用 sudo(谨慎)
sudo python3 scripts/find_large_files.py /扫描太慢
# 限制扫描深度(只扫描指定目录)
python3 scripts/find_large_files.py ~/Downloads --max-results 50JSON 导出失败
# 确保目录存在
mkdir -p /tmp
python3 scripts/find_garbage.py ~ --export /tmp/scan.json#!/usr/bin/env python3
"""
交互式文件清理工具
"""
import json
import shutil
from pathlib import Path
from datetime import datetime
def load_scan_results(json_path):
"""
加载扫描结果
Args:
json_path: JSON 文件路径
Returns:
扫描结果字典
"""
json_path = Path(json_path).expanduser()
if not json_path.exists():
print(f"❌ 扫描结果文件不存在: {json_path}")
return None
with open(json_path, 'r') as f:
return json.load(f)
def display_selection_menu(results, scan_type='garbage'):
"""
显示选择菜单
Args:
results: 扫描结果
scan_type: 扫描类型 ('garbage' 或 'large')
Returns:
用户选择的文件列表
"""
if scan_type == 'garbage':
return display_garbage_menu(results)
elif scan_type == 'large':
return display_large_files_menu(results)
else:
print(f"❌ 未知的扫描类型: {scan_type}")
return []
def display_garbage_menu(results):
"""
显示垃圾文件选择菜单
Args:
results: 垃圾文件扫描结果
Returns:
用户选择的文件列表
"""
selected_files = []
print("╔═══════════════════════════════════════════════════════════════╗")
print("║ 选择要清理的垃圾文件 ║")
print("╚═══════════════════════════════════════════════════════════════╝")
print()
# 按类别显示
categories = [c for c in results.keys() if c != 'summary']
for category in categories:
data = results[category]
files = data.get('files', [])
if not files:
continue
description = data.get('description', '')
count = data.get('count', 0)
size_mb = data.get('total_size_mb', 0)
safe_to_delete = data.get('safe_to_delete', False)
# 显示类别信息
status_icon = "🟢" if safe_to_delete else "🟡"
print(f"{status_icon} {description} ({count} 个文件, {size_mb:.2f} MB)")
# 询问是否清理该类别
if safe_to_delete:
print(f" [A] 全选 [S] 跳过")
print(f" [1-{count}] 选择文件")
# 简化:全选或跳过
while True:
choice = input(f" 清理全部 [A/S]? ").strip().upper()
if choice == 'A':
selected_files.extend(files)
print(f" ✅ 已选择全部 {count} 个文件")
break
elif choice == 'S':
print(f" ⏭️ 跳过")
break
else:
print(" 请输入 A 或 S")
else:
print(f" [S] 跳过 (需要手动确认)")
while True:
choice = input(f" 跳过 [S/Y]? ").strip().upper()
if choice == 'S':
print(f" ⏭️ 跳过")
break
elif choice == 'Y':
print(f" ⏭️ 跳过")
break
else:
print(" 请输入 S 或 Y")
print()
return selected_files
def display_large_files_menu(results):
"""
显示大文件选择菜单
Args:
results: 大文件扫描结果
Returns:
用户选择的文件列表
"""
selected_files = []
print("╔═══════════════════════════════════════════════════════════════╗")
print("║ 选择要清理的大文件 ║")
print("╚═══════════════════════════════════════════════════════════════╝")
print()
# 显示文件列表
for i, file in enumerate(results, 1):
size_icon = "🔴" if file['size_mb'] > 1000 else \
"🟠" if file['size_mb'] > 100 else "🟡"
print(f"{i:2d}. {size_icon} {file['size_mb']:8.2f} MB")
print(f" 📁 {file['name']}")
# 显示相对路径
home = Path.home()
try:
relative = Path(file['path']).relative_to(home)
print(f" 📍 ~/{relative}")
except ValueError:
short_path = file['path'][:60]
print(f" 📍 {short_path}{'...' if len(file['path']) > 60 else ''}")
print()
# 选择文件
print("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
print()
print("输入要删除的文件编号(用逗号分隔,或 'all' 删除全部)")
print("输入 'cancel' 取消")
print()
while True:
choice = input("选择: ").strip()
if choice.lower() == 'cancel':
print("❌ 已取消")
return []
elif choice.lower() == 'all':
selected_files = results.copy()
print(f"✅ 已选择全部 {len(results)} 个文件")
break
else:
# 解析编号
try:
indices = [int(x.strip()) - 1 for x in choice.split(',')]
# 验证索引
valid_indices = []
for idx in indices:
if 0 <= idx < len(results):
valid_indices.append(idx)
else:
print(f"⚠️ 无效的编号: {idx + 1}")
selected_files = [results[i] for i in valid_indices]
print(f"✅ 已选择 {len(selected_files)} 个文件")
break
except ValueError:
print("❌ 输入格式错误,请输入编号(如: 1,3,5)")
return selected_files
def confirm_cleanup(files):
"""
确认清理操作
Args:
files: 要清理的文件列表
Returns:
是否确认清理
"""
if not files:
print("❌ 没有选择任何文件")
return False
print("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
print()
print("⚠️ 确认清理")
print()
print(f"将删除 {len(files)} 个文件")
total_size = sum(f.get('size_bytes', f.get('size_mb', 0) * 1024 * 1024)
for f in files)
print(f"总大小: {total_size / (1024 * 1024 * 1024):.2f} GB")
print()
# 显示前几个文件
for file in files[:5]:
print(f" • {file.get('name', file.get('path', ''))}")
if len(files) > 5:
print(f" ... 和其他 {len(files) - 5} 个文件")
print()
print("⚠️ 此操作不可撤销!")
print()
choice = input("确认删除 [yes/no]? ").strip().lower()
return choice in ['yes', 'y']
def cleanup_files(files, dry_run=False):
"""
清理文件
Args:
files: 要清理的文件列表
dry_run: 是否为预演模式(不实际删除)
Returns:
成功删除的文件数量
"""
if not files:
return 0
print()
print("🗑️ 开始清理...")
print()
if dry_run:
print("🔍 预演模式(不会实际删除文件)")
print()
success_count = 0
failed_count = 0
for file in files:
file_path = file.get('path')
if not file_path:
continue
try:
if dry_run:
print(f" [PRETEND] 删除: {file_path}")
success_count += 1
else:
# 删除文件或目录
path_obj = Path(file_path)
if path_obj.is_dir():
shutil.rmtree(path_obj)
else:
path_obj.unlink()
print(f" ✅ 已删除: {file.get('name', file_path)}")
success_count += 1
except Exception as e:
print(f" ❌ 删除失败: {file.get('name', file_path)}")
print(f" 错误: {e}")
failed_count += 1
print()
print(f"📊 清理完成:")
print(f" 成功: {success_count}")
print(f" 失败: {failed_count}")
return success_count
def main():
import argparse
parser = argparse.ArgumentParser(description="交互式文件清理工具")
parser.add_argument('scan_result', help='扫描结果 JSON 文件')
parser.add_argument('--type', choices=['garbage', 'large'],
default='garbage',
help='扫描结果类型(默认: garbage)')
parser.add_argument('--dry-run', action='store_true',
help='预演模式,不实际删除文件')
args = parser.parse_args()
# 加载扫描结果
print(f"📂 加载扫描结果: {args.scan_result}")
print()
results = load_scan_results(args.scan_result)
if not results:
print("❌ 无法加载扫描结果")
return
# 显示选择菜单
selected_files = display_selection_menu(results, scan_type=args.type)
if not selected_files:
print("❌ 没有选择任何文件")
return
# 确认清理
if not confirm_cleanup(selected_files):
print("❌ 已取消清理")
return
# 执行清理
cleanup_files(selected_files, dry_run=args.dry_run)
if __name__ == "__main__":
main()
#!/bin/bash
# 文件清理工具 - 主启动脚本
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
case "$1" in
# 扫描大文件
large)
shift
python3 "$SCRIPT_DIR/scripts/find_large_files.py" "$@"
;;
# 扫描垃圾文件
garbage)
shift
python3 "$SCRIPT_DIR/scripts/find_garbage.py" "$@"
;;
# 交互式清理
clean)
shift
python3 "$SCRIPT_DIR/scripts/clean_interactive.py" "$@"
;;
# 快速扫描(大文件 + 垃圾文件)
quick)
echo "╔═══════════════════════════════════════════════════════════════╗"
echo("║ 快速文件扫描 ║")
echo("╚═══════════════════════════════════════════════════════════════╝")
echo()
echo "1. 扫描大文件(>10MB)"
python3 "$SCRIPT_DIR/scripts/find_large_files.py" --show 10
echo()
echo "2. 扫描垃圾文件"
python3 "$SCRIPT_DIR/scripts/find_garbage.py" --show 5
echo()
echo "💡 要清理文件,使用:"
echo(" file-cleaner clean <scan_result.json>")
;;
# 帮助
help|--help|-h)
cat << 'EOF'
文件清理工具 - 扫描和清理大文件、垃圾文件
用法:
file-cleaner <command> [options]
命令:
large <directory> [options] 扫描大文件
garbage <directory> [options] 扫描垃圾文件
clean <scan_result.json> 交互式清理
quick 快速扫描(大文件 + 垃圾)
选项:
large 命令:
--min-size <MB> 最小文件大小(默认: 10)
--max-results <N> 最大结果数(默认: 100)
--show <N> 显示的文件数(默认: 20)
--export <path> 导出到 JSON
garbage 命令:
--categories <cat1,cat2> 指定扫描类别
--show <N> 每个类别显示的文件数(默认: 10)
--export <path> 导出到 JSON
--script <path> 生成清理脚本
clean 命令:
--type <garbage|large> 扫描结果类型(默认: garbage)
--dry-run 预演模式(不实际删除)
示例:
# 扫描大文件
file-cleaner large ~
# 扫描大于 50MB 的文件
file-cleaner large ~ --min-size 50
# 扫描垃圾文件
file-cleaner garbage ~
# 只扫描缓存文件
file-cleaner garbage ~ --categories cache_files temp_files
# 导出扫描结果
file-cleaner garbage ~ --export garbage_scan.json
# 交互式清理
file-cleaner clean garbage_scan.json
# 预演清理(不实际删除)
file-cleaner clean garbage_scan.json --dry-run
# 快速扫描
file-cleaner quick
垃圾文件类别:
temp_files - 临时文件
cache_files - 缓存文件
log_files - 日志文件
backup_files - 备份文件
build_artifacts - 构建产物
editor_temp - 编辑器临时文件
download_temp - 下载临时文件
安全提示:
• 查看文件内容再删除
• 先用 --dry-run 预演
• 日志文件可能需要保留
• 备份重要文件
EOF
;;
*)
echo "文件清理工具"
echo ""
echo "使用 'file-cleaner help' 查看所有命令"
echo ""
echo "快速开始:"
echo " file-cleaner large ~ # 扫描大文件"
echo " file-cleaner garbage ~ # 扫描垃圾文件"
echo " file-cleaner quick # 快速扫描"
echo " file-cleaner clean results.json # 交互式清理"
;;
esac
#!/usr/bin/env python3
"""
垃圾文件扫描器 - 扫描并识别垃圾文件(临时文件、缓存等)
"""
import os
import json
from pathlib import Path
from datetime import datetime
# 垃圾文件模式
GARBAGE_PATTERNS = {
# 临时文件
'temp_files': {
'extensions': ['.tmp', '.temp', '.bak', '.swp', '.DS_Store'],
'patterns': ['*.tmp', '*.temp', '*.bak'],
'description': '临时文件',
'safe_to_delete': True
},
# 缓存文件
'cache_files': {
'extensions': ['.cache'],
'patterns': ['__pycache__', '*.pyc', '.pytest_cache'],
'directories': ['__pycache__', '.cache', 'Cache', 'node_modules/.cache'],
'description': '缓存文件',
'safe_to_delete': True
},
# 日志文件
'log_files': {
'extensions': ['.log'],
'patterns': ['*.log'],
'description': '日志文件',
'safe_to_delete': False # 日志可能需要用于调试
},
# 备份文件
'backup_files': {
'extensions': ['.backup', '.old'],
'patterns': ['*.backup', '*.old'],
'description': '备份文件',
'safe_to_delete': True
},
# 构建产物
'build_artifacts': {
'directories': ['dist', 'build', '.next', 'out', 'target'],
'description': '构建产物',
'safe_to_delete': True
},
# 编辑器临时文件
'editor_temp': {
'extensions': ['.swo', '.swn', '.un~'],
'patterns': ['.git/*.rej', '*.orig'],
'description': '编辑器临时文件',
'safe_to_delete': True
},
# 下载临时文件
'download_temp': {
'extensions': ['.crdownload', '.part', '.download'],
'description': '下载临时文件',
'safe_to_delete': True
}
}
# 排除的目录(重要系统目录)
EXCLUDE_DIRS = {
'/proc',
'/sys',
'/dev',
'/run',
'/tmp',
'/var/tmp',
'/usr',
'/bin',
'/sbin',
'/lib',
'.git',
'.svn',
'.hg',
}
def scan_for_garbage(directory, categories=None):
"""
扫描目录,找出垃圾文件
Args:
directory: 要扫描的目录
categories: 要扫描的垃圾类型(None = 全部)
Returns:
垃圾文件列表,按类别分类
"""
directory = Path(directory).expanduser()
if not directory.exists():
print(f"❌ 目录不存在: {directory}")
return {}
print(f"🔍 扫描目录: {directory}")
print()
# 确定要扫描的类别
if categories is None:
categories = list(GARBAGE_PATTERNS.keys())
else:
categories = [c for c in categories if c in GARBAGE_PATTERNS]
# 结果
garbage_files = {category: [] for category in categories}
# 总统计
total_files = 0
total_size = 0
for root, dirs, files in os.walk(directory):
# 移除排除的目录
dirs[:] = [d for d in dirs if d not in EXCLUDE_DIRS]
for file in files:
file_path = Path(root) / file
try:
# 获取文件信息
stat = file_path.stat()
size = stat.st_size
extension = file_path.suffix.lower()
filename = file_path.name.lower()
parent_dir = file_path.parent.name
# 检查每个类别
for category in categories:
pattern_info = GARBAGE_PATTERNS[category]
# 检查扩展名
if 'extensions' in pattern_info:
if extension in pattern_info['extensions']:
garbage_files[category].append({
'path': str(file_path),
'name': file,
'size_mb': size / (1024 * 1024),
'size_bytes': size,
'extension': extension,
'category': category,
'description': pattern_info['description'],
'safe_to_delete': pattern_info['safe_to_delete'],
'parent': str(file_path.parent)
})
total_files += 1
total_size += size
break
# 检查目录名
elif 'directories' in pattern_info:
if parent_dir in pattern_info['directories']:
# 整个目录都算作垃圾
garbage_files[category].append({
'path': str(file_path),
'name': file,
'size_mb': size / (1024 * 1024),
'size_bytes': size,
'extension': extension,
'category': category,
'description': pattern_info['description'],
'safe_to_delete': pattern_info['safe_to_delete'],
'parent': str(file_path.parent),
'is_directory': parent_dir
})
total_files += 1
total_size += size
break
# 检查文件名模式
elif 'patterns' in pattern_info:
for pattern in pattern_info['patterns']:
# 简单的通配符匹配
if pattern.startswith('*.'):
pattern_ext = pattern[1:]
if extension == pattern_ext:
garbage_files[category].append({
'path': str(file_path),
'name': file,
'size_mb': size / (1024 * 1024),
'size_bytes': size,
'extension': extension,
'category': category,
'description': pattern_info['description'],
'safe_to_delete': pattern_info['safe_to_delete'],
'parent': str(file_path.parent)
})
total_files += 1
total_size += size
break
except (OSError, PermissionError) as e:
# 跳过无权限的文件
continue
# 按类别汇总
for category in categories:
files = garbage_files[category]
category_size = sum(f['size_bytes'] for f in files)
garbage_files[category] = {
'files': files,
'count': len(files),
'total_size_mb': category_size / (1024 * 1024),
'description': GARBAGE_PATTERNS[category]['description'],
'safe_to_delete': GARBAGE_PATTERNS[category]['safe_to_delete']
}
# 总计
garbage_files['summary'] = {
'total_files': total_files,
'total_size_mb': total_size / (1024 * 1024),
'categories_scanned': len(categories)
}
return garbage_files
def print_garbage_results(results, show_details=10):
"""
打印垃圾文件扫描结果
Args:
results: 扫描结果
show_details: 每个类别显示的详细数量
"""
if not results:
print("❌ 没有扫描到垃圾文件")
return
summary = results.get('summary', {})
print("╔═════════════════════════════════════════════════════════════════╗")
print("║ 垃圾文件扫描结果 ║")
print("╚═════════════════════════════════════════════════════════════════╝")
print()
# 摘要
print("📊 扫描摘要")
print()
print(f" 扫描类别: {summary.get('categories_scanned', 0)}")
print(f" 垃圾文件: {summary.get('total_files', 0)} 个")
print(f" 总大小: {summary.get('total_size_mb', 0):.2f} MB")
print()
# 按类别显示
categories = [c for c in results.keys() if c != 'summary']
if not categories:
print("✅ 没有发现垃圾文件!")
return
print("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
print()
total_safe = 0
total_unsafe = 0
for category in categories:
if category == 'summary':
continue
data = results[category]
files = data.get('files', [])
count = data.get('count', 0)
size_mb = data.get('total_size_mb', 0)
description = data.get('description', '')
safe_to_delete = data.get('safe_to_delete', False)
if count == 0:
continue
# 状态图标
if safe_to_delete:
status_icon = "🟢"
status_text = "安全删除"
total_safe += count
else:
status_icon = "🟡"
status_text = "需确认"
total_unsafe += count
print(f"{status_icon} {description} ({count} 个, {size_mb:.2f} MB)")
print(f" 状态: {status_text}")
# 显示前几个文件
for i, file in enumerate(files[:show_details], 1):
relative = Path(file['path'])
try:
home = Path.home()
relative = relative.relative_to(home)
display_path = f"~/{relative}"
except ValueError:
display_path = file['path'][:60]
print(f" {i}. {file['name'][:50]}")
print(f" 📁 {display_path}")
if count > show_details:
print(f" ... 还有 {count - show_details} 个文件")
print()
# 安全提示
print("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")
print()
print(f"🟢 可安全删除: {total_safe} 个文件")
print(f"🟡 需要确认: {total_unsafe} 个文件(日志、备份等)")
print()
print("💡 提示:")
print(" • 查看文件内容再删除,确认没有重要数据")
print(" • 日志文件可以先归档,一段时间后再删除")
print(" • 缓存文件可以安全删除,会自动重建")
def generate_cleanup_script(results, output_path):
"""
生成清理脚本
Args:
results: 扫描结果
output_path: 输出脚本路径
"""
with open(output_path, 'w') as f:
f.write("#!/bin/bash\n")
f.write(f"# 自动生成的垃圾文件清理脚本\n")
f.write(f"# 生成时间: {datetime.now().isoformat()}\n")
f.write(f"# ⚠️ 使用前请仔细检查!\n\n")
f.write("echo \"🗑️ 垃圾文件清理脚本\"\n")
f.write("echo \"=\"\n\n")
# 只包含安全删除的文件
for category in results.keys():
if category == 'summary':
continue
data = results[category]
if not data.get('safe_to_delete', False):
f.write(f"# ⚠️ 跳过 {data.get('description')} (需要手动确认)\n\n")
continue
files = data.get('files', [])
for file in files:
f.write(f"rm -f \"{file['path']}\"\n")
f.write("\necho \"✅ 清理完成\"\n")
f.write("echo \"⚠️ 请确认没有误删!\"\n")
print(f"✅ 清理脚本已生成: {output_path}")
def main():
import argparse
parser = argparse.ArgumentParser(description="垃圾文件扫描器")
parser.add_argument('directory', nargs='?', default='~',
help='要扫描的目录(默认: ~)')
parser.add_argument('--categories', nargs='+',
choices=list(GARBAGE_PATTERNS.keys()),
help='要扫描的垃圾类型(默认: 全部)')
parser.add_argument('--show', type=int, default=10,
help='每个类别显示的文件数量(默认: 10)')
parser.add_argument('--export', help='导出结果到 JSON 文件')
parser.add_argument('--script', help='生成清理脚本路径')
args = parser.parse_args()
# 展开路径
directory = Path(args.directory).expanduser()
# 扫描
results = scan_for_garbage(
directory,
categories=args.categories
)
# 显示结果
print_garbage_results(results, show_details=args.show)
# 导出结果
if args.export:
export_path = Path(args.export).expanduser()
with open(export_path, 'w') as f:
json.dump(results, f, indent=2, ensure_ascii=False)
print(f"✅ 结果已导出到: {export_path}")
# 生成清理脚本
if args.script:
script_path = Path(args.script).expanduser()
generate_cleanup_script(results, script_path)
if __name__ == "__main__":
main()
#!/usr/bin/env python3
"""
大文件扫描器 - 扫描指定目录,找出大文件
"""
import os
import json
from pathlib import Path
from datetime import datetime
def find_large_files(directory, min_size_mb=10, max_results=100):
"""
扫描目录,找出大于指定大小的文件
Args:
directory: 要扫描的目录
min_size_mb: 最小文件大小(MB)
max_results: 最大返回结果数
Returns:
文件列表,按大小排序
"""
directory = Path(directory)
if not directory.exists():
print(f"❌ 目录不存在: {directory}")
return []
print(f"🔍 扫描目录: {directory}")
print(f" 最小大小: {min_size_mb} MB")
print(f" 最大结果: {max_results}")
print()
large_files = []
min_size_bytes = min_size_mb * 1024 * 1024
# 排除的目录
exclude_dirs = {
'.git',
'__pycache__',
'node_modules',
'.venv',
'venv',
'env',
'.cache',
'Cache',
'Trash',
'.Trash'
}
# 排除的文件类型(可扩展)
exclude_extensions = {
'.pyc',
'.pyo',
'.pyd',
}
print("扫描中... (按 Ctrl+C 停止)")
print()
count = 0
for root, dirs, files in os.walk(directory):
# 移除排除的目录
dirs[:] = [d for d in dirs if d not in exclude_dirs]
for file in files:
file_path = Path(root) / file
try:
size = file_path.stat().st_size
# 检查文件大小
if size >= min_size_bytes:
# 检查文件扩展名
if file_path.suffix not in exclude_extensions:
count += 1
large_files.append({
'path': str(file_path),
'name': file,
'size_mb': size / (1024 * 1024),
'size_bytes': size,
'extension': file_path.suffix,
'parent': str(file_path.parent)
})
# 限制结果数量
if len(large_files) >= max_results:
print(f"⚠️ 已达到最大结果数: {max_results}")
break
except (OSError, PermissionError) as e:
# 跳过无权限的文件
continue
# 按大小降序排序
large_files.sort(key=lambda x: x['size_bytes'], reverse=True)
return large_files
def print_large_files(files, show_count=20):
"""
打印大文件列表
Args:
files: 文件列表
show_count: 显示的文件数量
"""
if not files:
print("❌ 没有找到大文件")
return
print("╔═══════════════════════════════════════════════════════════════╗")
print("║ 大文件列表 ║")
print("╚═══════════════════════════════════════════════════════════════╝")
print()
# 显示前 N 个文件
display_files = files[:show_count]
total_size = sum(f['size_bytes'] for f in files)
print(f"📊 找到 {len(files)} 个大文件,显示前 {len(display_files)} 个")
print(f" 总大小: {total_size / (1024*1024*1024):.2f} GB")
print()
for i, file in enumerate(display_files, 1):
size_icon = "🔴" if file['size_mb'] > 1000 else \
"🟠" if file['size_mb'] > 100 else "🟡"
print(f"{i:2d}. {size_icon} {file['size_mb']:8.2f} MB {file['name']}")
# 显示相对路径
home = Path.home()
try:
relative = Path(file['path']).relative_to(home)
print(f" 📁 {relative}")
except ValueError:
# 不在 home 目录下
print(f" 📁 {file['path'][:60]}{'...' if len(file['path']) > 60 else ''}")
print()
if len(files) > show_count:
print(f"... 还有 {len(files) - show_count} 个文件")
print()
def export_to_json(files, output_path):
"""
导出结果到 JSON 文件
Args:
files: 文件列表
output_path: 输出文件路径
"""
with open(output_path, 'w') as f:
json.dump(files, f, indent=2, ensure_ascii=False)
print(f"✅ 结果已导出到: {output_path}")
def main():
import argparse
parser = argparse.ArgumentParser(description="大文件扫描器")
parser.add_argument('directory', nargs='?', default='~',
help='要扫描的目录(默认: ~)')
parser.add_argument('--min-size', type=float, default=10,
help='最小文件大小(MB),默认: 10')
parser.add_argument('--max-results', type=int, default=100,
help='最大结果数,默认: 100')
parser.add_argument('--show', type=int, default=20,
help='显示的文件数量,默认: 20')
parser.add_argument('--export', help='导出结果到 JSON 文件')
args = parser.parse_args()
# 展开 ~
directory = Path(args.directory).expanduser()
# 扫描
files = find_large_files(
directory,
min_size_mb=args.min_size,
max_results=args.max_results
)
# 显示结果
print_large_files(files, show_count=args.show)
# 导出(如果需要)
if args.export:
export_path = Path(args.export).expanduser()
export_to_json(files, export_path)
if __name__ == "__main__":
main()
Related skills
FAQ
Is it safe?
It auto-excludes system, version-control, and Python-env directories and offers a --dry-run mode to preview deletions.
What counts as junk?
Seven categories: temp files, caches, logs, backups, build artifacts, editor temp files, and download temp files.