自动化脚本如何清理未使用文件

wen 实用脚本 25

本文目录导读:

自动化脚本如何清理未使用文件

  1. 基础文件清理脚本
  2. 代码项目未使用文件检测
  3. 系统级未使用文件检测
  4. 智能文件清理系统
  5. 实用的清理脚本组合
  6. 使用建议

我来介绍几种自动化清理未使用文件的方法,从简单到复杂:

基础文件清理脚本

按时间清理旧文件(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 "$@"

使用建议

  1. 先试运行:在自动化之前先用 --dry-run-n 测试
  2. 备份重要数据:清理前确认备份
  3. 设置白名单:保护重要文件不被误删
  4. 定期执行:使用 cron 定期运行
  5. 记录日志:记录删除操作以便审计

这些脚本可以根据具体需求调整,建议先在小范围测试再全面部署。

抱歉,评论功能暂时关闭!