关注【索引目录】服务号,更多精彩内容等你来探索!
前段时间,在学习 Bash 脚本时,我尝试深入研究这个主题,并通过解决各种任务(哪怕是最小的任务)来寻求更多练习。其中一个脚本可以删除临时文件、旧转储文件以及被遗忘已久的项目的 node_modules 文件夹。前几天我偶然发现了它。我在虚拟机上测试了它,虽然可以运行,但代码非常粗糙,而且视觉效果很差。
我当时有什么想法?想看看 ChatGPT 能否做到和我一样(以及做得有多好),而且做得更好。结果很有启发性:AI 在架构方面做得很好,但实际上却试图用几行代码毁掉整个系统。下面我会告诉你它是怎么回事。
任务很简单,你需要根据某些规则自动查找并删除不需要的文件。我以前的脚本简直就是个庞然大物:一堆重复的 find 和 rm -rfa 等笨拙的尝试来处理错误。请不要提前对我做出过多的评判,我当时只是在学习 Bash 及其功能。
我创作中的主要问题
带有变量连接的命令 rm -rf 是俄罗斯轮盘赌游戏(连接是将两个或多个字符串组合成一个)。
路径和脚本中的任何间隙都会默默地“飞过”目标或删除错误的东西。
要更改规则,您需要直接进入代码,一开始没有适当的设置。
该脚本没有记录它删除了什么(或者根本没删除什么?)。它默默地运行着,这总是令人担忧。
我给 ChatGPT 发送了 TOR:“编写一个安全且可自定义的脚本来搜索/删除临时文件、缓存和旧日志。添加一个无法访问的文件夹白名单。添加日志记录。”
前后逐步代码分析
我先来演示一下那个让我感到无比羞愧的“作弊”脚本。分享它真的不容易。以下是
我的版本(为了方便理解,我在写这篇文章之前加了一些评论)。
#!/bin/bash
# If $DIR contains a space, the command will split into two
DIRS="/tmp ~/cache ~/projects/*/node_modules"
# Remove everything at once
for dir in $DIRS; do
echo "Removing $dir"
rm -rf "$dir" # Quotes are here, but the for loop breaks them anyway, right?
done
# Find and delete all .log and .tmp files older than 30 days
find ~/ -name "*.log" -mtime +30 -exec rm {} \; 2>/dev/null
find ~/ -name "*.tmp" -mtime +30 -exec rm {} \; 2>/dev/null
echo "Cleanup done!"
这段代码完全是出于极度的懒惰(毕竟,他本可以“读读互联网”然后做得更好……)。它递归地删除了 node_modules,甚至没有查看文件,还默默地忽略了所有错误( 2>/dev/null ),从而隐藏了现有的权限问题。
ChatGPT 的 Python 版本
我想提前指出,选择 Python 并非偶然,而是经过深思熟虑的选择。我想强调的是,“随身携带的脚本”和经过深思熟虑的可靠工具之间的区别。
ChatGPT 的使命是开发高质量且安全的软件,他们直觉地知道 Bash 并非完成这项工作的合适工具。任何脚本的核心在于安全性,而 Bash 没有内置的安全文件删除机制。安全性实际上取决于正确的转义,以及避免变量意外为空。
我给出的提示是:“编写一个安全且可配置的系统清理脚本。它应该删除旧文件,列出危险目录(例如 /、/home 等)的黑名单,并将其操作记录到文件中。避免直接使用 shell 命令。”
这是 AI 的建议(添加了我的评论和后续编辑)
# cleanup_agent.py
import os
import logging
import time
from pathlib import Path
# === CONFIGURATION ===
TARGETS = [
{
"path": os.path.expanduser("~/Downloads"),
"patterns": ["*.tmp", "*.temp", "*.log"],
"max_age_days": 7
},
{
"path": os.path.expanduser("~/.cache"),
"patterns": ["*"],
"max_age_days": 30
}
]
# Directories that must never be touched (!)
BLOCKLIST = {
os.path.expanduser("/"),
os.path.expanduser("~"),
os.path.expanduser("~/.ssh"),
}
# Logging setup
logging.basicConfig(
filename=os.path.expanduser('~/cleanup_agent.log'),
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
def safe_remove(target: Path):
"""Safely remove a file or empty folder with logging"""
try:
if target.is_file():
target.unlink() # Remove file
logging.info(f"Removed file: {target}")
elif target.is_dir():
target.rmdir() # Remove empty folder only
logging.info(f"Removed empty folder: {target}")
except OSError as e:
# Log error but don't crash
logging.error(f"Failed to remove {target}: {e}")
def cleanup_directory(config: dict):
"""Clean a directory based on config"""
base_dir = Path(config["path"])
if not base_dir.exists():
logging.warning(f"Directory not found: {base_dir}")
return
# Check if directory is in blocklist
if any(blocked in base_dir.parents for blocked in BLOCKLIST):
logging.error(f"Attempted cleanup of protected directory: {base_dir}. Aborting.")
return
current_time = time.time()
for pattern in config["patterns"]:
for target in base_dir.rglob(pattern): # Recursive search
if not target.exists():
continue
# Check file/folder age
age_days = (current_time - target.stat().st_mtime) / (60 * 60 * 24)
if age_days > config["max_age_days"]:
safe_remove(target)
if __name__ == "__main__":
logging.info("=== Cleanup started ===")
for job in TARGETS:
cleanup_directory(job)
logging.info("=== Cleanup finished ===\n")
比较分析
ChatGPT 的正确之处:
尽可能确保脚本的安全。使用 Python 内置方法(unlink、rmdir)消除了 rm -rfdirect 等调用。$HOME 目录下出现了一个黑名单,它完全禁止任何进入 /or 目录的尝试。
增加了可定制性。与其硬编码,不如采用字典列表形式的配置,其中包含目标。需要清理其他文件夹或更改“年龄”?只需编辑列表即可,无需更改代码。在我看来,这是一个正确且有效的解决方案。
该脚本现在维护一个完整的日志文件。现在您不仅可以看到删除的内容,还可以了解出错的原因。
使用 pathlib.Path 代替字符串连接,这更适合处理路径。它会自动处理不同的操作系统并转义特殊字符。
ChatGPT 不太正确的地方(在我看来,如果我错了,请纠正我)
递归搜索有点危险。最初,AI 使用 base_dir.rglob(' ') 来查找 ~/.cache 中的模式“ ”。这字面意思是:“递归遍历缓存中的所有内容,并检查每个文件的使用期限”。对于缓存目录来说,由于其中包含大量小文件,这很容易导致极其漫长且无用的工作。为了进行如此激进的清理,我建议添加一个最小使用期限的条件。
模仿安全性。函数 safe_remove 仅在文件夹为空时尝试删除文件夹。这很安全,但对 node_modules 来说完全没用。对于“非空”目录,脚本会直接忽略它们。最好在日志中明确指定这一点。
这不是最实用的模板。模板“ ~/.cache ”太宽了。更正确的格式应该是:[' .bin', 'cache/ ', 'thumbnails/ '] 等。
可以得出什么结论:ChatGPT 将一个质量低下且略带危险的 Bash 脚本变成了一个几乎可以用于生产的实用程序,并附带配置和日志。但盲目地相信“所有事物和所有人”的递归遍历很容易导致系统瘫痪。AI 可以完美地构建和保护代码,但它似乎缺乏对“我到底应该清理什么”的具体理解。作为生成的辅助工具,它是必不可少的,但你需要充分了解相关内容并非常仔细地监控生成的代码,以避免危险的后果。
使用示例
与往常一样,脚本的说明在文章中(也许有人会需要它?)
将代码保存到文件 cleanup_agent.py。
我们编辑所需任务的配置目标。需要每周清理一次下载内容 - 请。需要从 pycache 中清理项目 - 我们添加了一条规则。
让我们启动它并查看日志。
# Make the script executable
chmod +x cleanup_agent.py
# Run the script
python3 cleanup_agent.py
检查日志输出
tail -f ~/cleanup_agent.log
The output in the log will be something like this:
2025-08-19 11:05:32,123 - INFO - === Cleanup started ===
2025-08-19 11:05:32,456 - INFO - Removed file: /home/user/Downloads/old_report.tmp
2025-08-19 11:05:33,001 - ERROR - Failed to remove /home/user/.cache/some_file: [Errno 13] Permission denied
2025-08-19 11:05:33,002 - INFO - === Cleanup finished ===
提示:仅当您确实需要接触受保护的路径时才使用 sudo 运行。否则,请保留权限错误信息。
关注【索引目录】服务号,更多精彩内容等你来探索!

