本文目录导读:

我来介绍几种自动化清理未使用文件的方法,从简单到复杂:
基础文件清理脚本
按时间清理旧文件(Shell)
#!/bin/bash
# 清理30天前的日志文件
find /var/log -name "*.log" -mtime +30 -exec rm {} \;
# 清理空文件
find . -type f -empty -delete
# 清理特定后缀的临时文件
find . -type f \( -name "*.tmp" -o -name "*.bak" \) -delete
Python版本
import os
import time
from pathlib import Path
def clean_old_files(directory, days=30, extensions=None):
"""清理指定目录中N天前的文件"""
now = time.time()
cutoff = now - (days * 86400)
for file in Path(directory).rglob('*'):
if file.is_file():
if extensions and file.suffix not in extensions:
continue
if file.stat().st_mtime < cutoff:
print(f"删除: {file}")
file.unlink()
# 使用示例
clean_old_files("/tmp", days=7, extensions=['.tmp', '.log'])
代码项目未使用文件检测
Git未追踪文件清理
#!/bin/bash
# 列出未被Git追踪的文件
git ls-files --others --exclude-standard | while read file; do
if [ -f "$file" ]; then
echo "未追踪: $file"
# 确认后删除
# rm "$file"
fi
done
Python项目引用检测
import ast
import os
from collections import defaultdict
class FileUsageAnalyzer:
def __init__(self, project_dir):
self.project_dir = project_dir
self.imports = defaultdict(set)
self.modules = set()
def analyze(self):
"""分析项目中所有Python文件的使用情况"""
for root, dirs, files in os.walk(self.project_dir):
for file in files:
if file.endswith('.py'):
filepath = os.path.join(root, file)
self._parse_file(filepath)
return self._find_unused()
def _parse_file(self, filepath):
"""解析单个Python文件"""
try:
with open(filepath, 'r') as f:
tree = ast.parse(f.read())
# 记录导入
for node in ast.walk(tree):
if isinstance(node, ast.Import):
for alias in node.names:
self.imports[filepath].add(alias.name)
elif isinstance(node, ast.ImportFrom):
self.imports[filepath].add(node.module)
except:
pass
def _find_unused(self):
"""查找未使用的模块文件"""
unused = []
for root, dirs, files in os.walk(self.project_dir):
for file in files:
if file.endswith('.py') and file != '__init__.py':
module_name = file[:-3]
if not self._is_module_used(module_name):
unused.append(os.path.join(root, file))
return unused
def _is_module_used(self, module_name):
"""检查模块是否被引用"""
for file, imports in self.imports.items():
if module_name in imports:
return True
return False
系统级未使用文件检测
Linux未使用文件清理脚本
#!/bin/bash
# 检查文件访问时间
echo "========== 未使用文件检测 =========="
# 1. 查找90天未访问的文件
echo "查找90天未访问的文件..."
find /path/to/scan -type f -atime +90 -exec ls -la {} \;
# 2. 查找大文件(>100MB)
echo "查找大文件..."
find /path/to/scan -type f -size +100M
# 3. 查找重复文件(使用md5)
echo "查找重复文件..."
find /path/to/scan -type f -exec md5sum {} \; | sort | uniq -d -w32
# 4. 查找空目录
echo "查找空目录..."
find /path/to/scan -type d -empty
智能文件清理系统
import os
import hashlib
import sqlite3
from datetime import datetime, timedelta
import logging
class SmartFileCleaner:
def __init__(self, db_path='file_usage.db'):
self.conn = sqlite3.connect(db_path)
self._init_db()
self.logger = logging.getLogger(__name__)
def _init_db(self):
"""初始化数据库"""
cursor = self.conn.cursor()
cursor.execute('''
CREATE TABLE IF NOT EXISTS file_usage (
path TEXT PRIMARY KEY,
last_accessed TIMESTAMP,
last_modified TIMESTAMP,
created TIMESTAMP,
size INTEGER,
checksum TEXT,
access_count INTEGER DEFAULT 0
)
''')
self.conn.commit()
def scan_files(self, directory):
"""扫描目录文件"""
for root, dirs, files in os.walk(directory):
for file in files:
filepath = os.path.join(root, file)
self._record_file(filepath)
def _record_file(self, filepath):
"""记录文件信息"""
try:
stat = os.stat(filepath)
checksum = self._get_file_hash(filepath)
cursor = self.conn.cursor()
cursor.execute('''
INSERT OR REPLACE INTO file_usage
VALUES (?, ?, ?, ?, ?, ?,
COALESCE((SELECT access_count FROM file_usage WHERE path=?), 0))
''', (
filepath,
datetime.fromtimestamp(stat.st_atime),
datetime.fromtimestamp(stat.st_mtime),
datetime.fromtimestamp(stat.st_ctime),
stat.st_size,
checksum,
filepath
))
self.conn.commit()
except Exception as e:
self.logger.error(f"扫描文件失败: {filepath} - {e}")
def _get_file_hash(self, filepath, blocksize=65536):
"""计算文件哈希"""
hasher = hashlib.md5()
try:
with open(filepath, 'rb') as f:
buf = f.read(blocksize)
while len(buf) > 0:
hasher.update(buf)
buf = f.read(blocksize)
return hasher.hexdigest()
except:
return None
def find_unused_files(self, months=3, min_size_mb=0):
"""查找未使用文件"""
cutoff_date = datetime.now() - timedelta(days=months*30)
min_size_bytes = min_size_mb * 1024 * 1024
cursor = self.conn.cursor()
cursor.execute('''
SELECT path, last_accessed, size FROM file_usage
WHERE last_accessed < ? AND size > ?
ORDER BY size DESC
''', (cutoff_date, min_size_bytes))
return cursor.fetchall()
def clean_files(self, dry_run=True):
"""清理未使用文件"""
unused_files = self.find_unused_files()
cleaned = []
for filepath, last_access, size in unused_files:
if dry_run:
print(f"[DRY RUN] 将删除: {filepath} (最后访问: {last_access}, 大小: {size/1024/1024:.2f}MB)")
else:
try:
os.remove(filepath)
# 从数据库删除记录
cursor = self.conn.cursor()
cursor.execute('DELETE FROM file_usage WHERE path=?', (filepath,))
self.conn.commit()
cleaned.append(filepath)
print(f"已删除: {filepath}")
except Exception as e:
print(f"删除失败: {filepath} - {e}")
return cleaned
def update_access_log(self, filepath):
"""更新文件访问记录"""
cursor = self.conn.cursor()
cursor.execute('''
UPDATE file_usage
SET last_accessed=?, access_count=access_count+1
WHERE path=?
''', (datetime.now(), filepath))
self.conn.commit()
# 使用示例
if __name__ == "__main__":
cleaner = SmartFileCleaner()
# 扫描指定目录
cleaner.scan_files("/path/to/scan")
# 查找180天未使用的文件
unused = cleaner.find_unused_files(months=6)
print(f"发现 {len(unused)} 个未使用文件")
# 模拟清理(dry run)
cleaner.clean_files(dry_run=True)
实用的清理脚本组合
#!/bin/bash
# ===== 综合文件清理系统 =====
CONFIG_FILE="~/.cleaner_config"
LOG_FILE="/var/log/file_cleaner.log"
# 读取配置
load_config() {
if [ -f "$CONFIG_FILE" ]; then
source "$CONFIG_FILE"
else
# 默认配置
CLEAN_DIRS=("/tmp" "/var/tmp" "~/Downloads")
OLD_DAYS=30
EXCLUDE_PATTERNS=("*.conf" "*.ini")
fi
}
# 清理临时文件
clean_temp_files() {
echo "=== 清理临时文件 ==="
for dir in "${CLEAN_DIRS[@]}"; do
if [ -d "$dir" ]; then
echo "扫描: $dir"
find "$dir" -type f -mtime +$OLD_DAYS | while read file; do
# 检查排除规则
skip=false
for pattern in "${EXCLUDE_PATTERNS[@]}"; do
if [[ "$file" == $pattern ]]; then
skip=true
break
fi
done
if [ "$skip" = false ]; then
echo " 删除: $file"
rm "$file" 2>/dev/null && echo "$(date): 删除 $file" >> "$LOG_FILE"
fi
done
fi
done
}
# 清理重复文件
clean_duplicate_files() {
echo "=== 清理重复文件 ==="
local dirs=("$@")
for dir in "${dirs[@]}"; do
if [ -d "$dir" ]; then
echo "扫描目录: $dir"
# 使用md5sum查找重复文件
find "$dir" -type f -exec md5sum {} \; | sort | \
awk '{
if ($1 == prev_hash) {
print $2
}
prev_hash = $1
}' | while read duplicate; do
echo " 重复文件: $duplicate"
# rm "$duplicate" # 取消注释以实际删除
done
fi
done
}
# 清理空目录
clean_empty_dirs() {
echo "=== 清理空目录 ==="
local dirs=("$@")
for dir in "${dirs[@]}"; do
if [ -d "$dir" ]; then
# 删除空目录(从最深层开始)
find "$dir" -type d -empty -delete -print | while read empty_dir; do
echo " 删除空目录: $empty_dir"
echo "$(date): 删除空目录 $empty_dir" >> "$LOG_FILE"
done
fi
done
}
# 生成报告
generate_report() {
echo "=== 清理报告 ==="
echo "扫描时间: $(date)"
echo "清理目录: ${CLEAN_DIRS[*]}"
echo "删除文件天数: $OLD_DAYS"
echo "排除模式: ${EXCLUDE_PATTERNS[*]}"
echo ""
# 统计各目录占用空间
for dir in "${CLEAN_DIRS[@]}"; do
if [ -d "$dir" ]; then
echo "目录: $dir"
du -sh "$dir" 2>/dev/null || echo " 无法访问"
fi
done
}
# 主函数
main() {
load_config
case "$1" in
clean)
clean_temp_files
clean_empty_dirs ${CLEAN_DIRS[@]}
;;
dedup)
clean_duplicate_files ${CLEAN_DIRS[@]}
;;
report)
generate_report
;;
*)
echo "使用方法: $0 {clean|dedup|report}"
echo " clean - 清理旧文件和空目录"
echo " dedup - 查找重复文件"
echo " report - 生成空间使用报告"
;;
esac
}
# 执行
main "$@"
使用建议
- 先试运行:在自动化之前先用
--dry-run或-n测试 - 备份重要数据:清理前确认备份
- 设置白名单:保护重要文件不被误删
- 定期执行:使用 cron 定期运行
- 记录日志:记录删除操作以便审计
这些脚本可以根据具体需求调整,建议先在小范围测试再全面部署。