Created
March 2, 2025 17:19
-
-
Save ShadowPower/94b70df964c46759dd2980f805ca6f32 to your computer and use it in GitHub Desktop.
remove .DS_Store and ._*
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
from collections import deque | |
# 可自定义的垃圾文件规则配置 | |
RULES = ( | |
{ | |
"name": "DS_Store files", | |
"match": lambda n: n == ".DS_Store", | |
"condition": lambda e: e.stat().st_size <= 1024**2, # 1MB | |
}, | |
{ | |
"name": "Resource fork files", | |
"match": lambda n: n.startswith("._"), | |
"condition": lambda e: e.stat().st_size <= 8*1024, # 8KB | |
} | |
) | |
def scan_directory(root: str) -> list[str]: | |
"""扫描目录并返回匹配文件列表""" | |
matched = [] | |
dirs = deque([root]) | |
while dirs: | |
current_dir = dirs.popleft() | |
try: | |
with os.scandir(current_dir) as it: | |
for entry in it: | |
try: | |
if entry.is_dir(follow_symlinks=False): | |
dirs.append(entry.path) | |
continue | |
for rule in RULES: | |
if rule["match"](entry.name): | |
try: | |
if rule["condition"](entry): | |
print(f"Found: {entry.path}") | |
matched.append(entry.path) | |
break # 匹配成功则跳过其他规则 | |
except OSError as e: | |
print(f"Error checking {entry.path}: {e}") | |
break # 跳过后续规则检查 | |
except OSError as e: | |
print(f"Error accessing {entry.path}: {e}") | |
except PermissionError: | |
print(f"Permission denied: {current_dir}") | |
except OSError as e: | |
print(f"Error scanning {current_dir}: {e}") | |
return matched | |
def delete_files(files: list[str]) -> int: | |
"""删除文件并返回成功数量""" | |
deleted = 0 | |
for path in files: | |
try: | |
os.remove(path) | |
print(f"Deleted: {path}") | |
deleted += 1 | |
except OSError as e: | |
print(f"Delete failed [{path}]: {e}") | |
return deleted | |
def main(): | |
path = input("Enter directory path: ").strip().strip('"').strip("'") | |
path = os.path.normpath(path) | |
if not os.path.isdir(path): | |
print("Error: Invalid directory path") | |
return | |
print("Scanning...") | |
matches = scan_directory(path) | |
if not matches: | |
print("No matching files found") | |
return | |
print(f"\nFound {len(matches)} files to delete") | |
if input("Confirm deletion? (y/n): ").strip().lower() == "y": | |
success = delete_files(matches) | |
print(f"Successfully deleted {success}/{len(matches)} files") | |
else: | |
print("Deletion canceled") | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment