<?php
//JSRUN引擎2.0,支持多达30种语言在线运行,全仿真在线交互输入输出。
echo 'Hello world - php.jsrun.net';
import os
import shutil
import platform
import time
import schedule
import logging
from typing import List, Tuple
# 配置日志记录
logging.basicConfig(
filename='cleaner.log',
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
class SystemCleaner:
def __init__(self):
self.system_os = platform.system()
self.logger = logging.getLogger(__name__)
self.safe_mode = True # 安全模式默认开启,只显示将要删除的文件
self.total_freed = 0 # 总共释放的空间(字节)
# 定义各系统需要清理的路径和文件类型
self.clean_targets = {
'Windows': [
(os.environ.get('TEMP', r'C:\Windows\Temp'), ['*.tmp', '*.log', '*.bak']),
(os.environ.get('LOCALAPPDATA', r'C:\Users\*\AppData\Local\Temp'), ['*']),
(os.path.expanduser('~\\AppData\\Local\\Microsoft\\Windows\\INetCache'), ['*']),
],
'Darwin': [ # macOS
('/Library/Caches', ['*']),
(os.path.expanduser('~/Library/Caches'), ['*']),
(os.path.expanduser('~/Library/Logs'), ['*.log']),
('/private/var/folders', ['*']),
],
'Linux': [
('/var/tmp', ['*']),
('/var/log', ['*.log']),
(os.path.expanduser('~/.cache'), ['*']),
(os.path.expanduser('~/Downloads'), ['*.tmp']),
]
}
def get_clean_list(self) -> List[Tuple[str, List[str]]]:
"""获取当前系统的清理目标列表"""
return self.clean_targets.get(self.system_os, [])
def safe_delete(self, path: str) -> None:
"""安全删除文件/目录"""
try:
if os.path.isfile(path):
os.remove(path)
self.logger.info(f"Deleted file: {path}")
self.total_freed += os.path.getsize(path)
elif os.path.isdir(path):
shutil.rmtree(path)
self.logger.info(f"Deleted directory: {path}")
# 计算目录大小需要额外处理,这里简略处理
except Exception as e:
self.logger.error(f"Error deleting {path}: {str(e)}", exc_info=True)
def scan_and_clean(self, dry_run=True) -> None:
"""扫描并清理垃圾文件"""
self.logger.info(f"Starting {'dry run' if dry_run else 'actual'} cleaning")
print(f"\n{' Dry Run Mode ' if dry_run else ' Cleaning Mode ':=^50}")
for target, patterns in self.get_clean_list():
target = os.path.expandvars(target) # 展开环境变量
try:
# 处理通配符路径(如Windows的AppData用户路径)
if '*' in target:
import glob
expanded_paths = glob.glob(target)
if not expanded_paths:
continue
else:
expanded_paths = [target]
for path in expanded_paths:
if not os.path.exists(path):
continue
# 处理不同文件模式
for pattern in patterns:
for root, dirs, files in os.walk(path):
for f in files:
file_path = os.path.join(root, f)
if self.should_delete(file_path, pattern):
print(f"Found: {file_path}")
if not dry_run:
self.safe_delete(file_path)
except Exception as e:
self.logger.error(f"Error processing {target}: {str(e)}", exc_info=True)
print(f"\nTotal space to free: {self.format_size(self.total_freed)}")
self.logger.info(f"Cleaning completed. Freed {self.format_size(self.total_freed)}")
@staticmethod
def should_delete(file_path: str, pattern: str) -> bool:
"""判断文件是否符合删除条件"""
filename = os.path.basename(file_path)
return (
filename.endswith('.tmp') or
filename.startswith('~$') or
filename == 'Thumbs.db' or
filename.endswith('.log') or
filename == 'desktop.ini' or
filename.endswith('.cache') or
filename.endswith('.bak') or
filename.endswith('.dmp') or
(pattern == '*' or filename.endswith(pattern[1:]))
)
@staticmethod
def format_size(size_bytes: int) -> str:
"""格式化存储空间大小"""
for unit in ['B', 'KB', 'MB', 'GB']:
if size_bytes < 1024.0:
return f"{size_bytes:.2f} {unit}"
size_bytes /= 1024.0
return f"{size_bytes:.2f} TB"
def run_scheduled_clean(self) -> None:
"""运行定时清理任务"""
schedule.every().day.at("02:00").do(self.scan_and_clean, dry_run=False)
print("Scheduler started. Will run daily at 2:00 AM")
while True:
schedule.run_pending()
time.sleep(60)
if __name__ == "__main__":
cleaner = SystemCleaner()
try:
# 首次运行使用安全模式(只显示不删除)
cleaner.scan_and_clean(dry_run=True)
# 用户确认后执行实际清理
if input("\nProceed with actual cleaning? (y/n): ").lower() == 'y':
cleaner.safe_mode = False
cleaner.scan_and_clean(dry_run=False)
# 是否设置定时任务
if input("\nSchedule daily cleaning at 12:00 AM? (y/n): ").lower() == 'y':
cleaner.run_scheduled_clean()
except KeyboardInterrupt:
print("\nOperation cancelled by user.")
logging.info("User cancelled the operation")
except Exception as e:
logging.critical(f"Critical error: {str(e)}", exc_info=True)
print(f"An error occurred: {str(e)}. Check cleaner.log for details.")