Привет, Хабр! Какое-то время назад, в процессе изучения bash‑скриптов, старался углубляться в тему и искал себе больше практики посредством решения любых, даже мельчайших задач. Одной из таких был скрипт, удаляющий временные файлы, старые дампы, папки node_modules от давно забытых проектов. Нашёл его на днях совершенно случайно. Протестил его на виртуалке, скрипт рабочий, но ужасно костыльный и неприятный визуально.

Какая у меня появилась идея? Проверить, сможет ли ChatGPT сделать то же (и насколько качественно), что и я, но грамотнее и «элегантнее». Результат получился весьма поучительным: ИИ отлично справился с архитектурой, но очень пытался угробить систему парой строчек. Далее расскажу, как это было.

Введение

Задача проста: нужно автоматически находить и удалять ненужные файлы по определенным правилам. Мой старый скрипт был монолитом: с кучей повторяющихся find и rm -rf, неловкими попытками обработки ошибок. Заранее прошу не осуждать сильно, я только изучал Bash и его возможности.

Главные проблемы моего творения:

  1. Команды rm -rf с конкатенацией переменных — игра в русскую рулетку (конкатенация — объединение двух или более строк в одну).

  2. Любой пробел в пути — и скрипт молча «пролетит» мимо цели или удалит не то.

  3. Чтобы поменять правила, нужно лезть непосредственно в код, нет грамотных настроек в начале.

  4. Скрипт не логировал, что именно он удалил (или не удалил?). Работал в тишине, что всегда тревожно.

Я скинул ChatGPT ТЗ: «Напиши безопасный и настраиваемый скрипт для поиска/удаления временных файлов, кэшей и старых логов. Добавь белый список папок, куда нельзя заходить. Добавь логирование».

Пошаговый разбор кода до и после

Начну с демонстрации того самого «костыльного» скрипта, за который мне крайне стыдно. Поделиться этим было действительно тяжело.

Моя версия (комментарии были добавлены мной перед написанием статьи для лучшего понимания):

#!/bin/bash

# Если в $DIR будет пробел, команда разобьется на две
DIRS="/tmp ~/cache ~/projects/*/node_modules"

# Удаляем всё и сразу
for dir in $DIRS; do
    echo "Удаляю $dir"
    rm -rf "$dir"  # Кавычки есть, но цикл for без кавычек их сломает (ведь так?)
done

# Поиск и удаление всех .log и .tmp файлы старше 30 дней
find ~/ -name "*.log" -mtime +30 -exec rm {} \; 2>/dev/null
find ~/ -name "*.tmp" -mtime +30 -exec rm {} \; 2>/dev/null

echo "Уборка завершена!"

Этот код - порождение колоссальной лени (ведь мог же "почитать интернет" и сделать лучше...). Он удаляет node_modules рекурсивно, не глядя, молча игнорирует любые ошибки (2>/dev/null), что может скрыть присутствующие проблемы с правами.

Версия от ChatGPT на Python:

Заранее хочу подметить, выбор Python - не случайность, а осознанный выбор. Я хотел подчеркнуть разницу подходов между "скриптом на коленке" и продуманным, надёжным инструментом.

ChatGPT, получив задачу сделать качественный и безопасный софт, интуитивно понимает, что Bash - не подходящий для задачи инструмент. Основной аспект любого скрипта - безопасность, а Bash не имеет встроенных механизмов для безопасного удаления файлов. Безопасность зависит буквально от правильного экранирования и надежды, что ни одна переменная не окажется случайно пустой.

Я дал промпт: "Write a safe and configurable system cleanup script. It should remove old files, have a blocklist for dangerous directories (like /, /home, etc.), and log its actions to a file. Avoid using shell commands directly".

Вот что предложил ИИ (были добавлены мои комментарии и последующая правка):

# cleanup_agent.py
import os
import logging
import time
from pathlib import Path

# === КОНФИГУРАЦИЯ ===
TARGETS = [
    {
        "path": os.path.expanduser("~/Downloads"),
        "patterns": ["*.tmp", "*.temp", "*.log"],
        "max_age_days": 7
    },
    {
        "path": os.path.expanduser("~/.cache"),
        "patterns": ["*"],
        "max_age_days": 30
    }
]

# Папки, которые нельзя удалять ни в коем случае (!)
BLOCKLIST = {
    os.path.expanduser("/"),
    os.path.expanduser("~"),
    os.path.expanduser("~/.ssh"),
}

# Настройка логирования
logging.basicConfig(
    filename=os.path.expanduser('~/cleanup_agent.log'),
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s'
)

def safe_remove(target: Path):
    """Безопасно удаляет файл или пустую папку с логированием"""
    try:
        if target.is_file():
            target.unlink()  # Удаление файла
            logging.info(f"Удален файл: {target}")
        elif target.is_dir():
            # Попытка удалить папку, только если она пуста
            target.rmdir()
            logging.info(f"Удалена пустая папка: {target}")
    except OSError as e:
        # Логируем ошибку, но не падаем :)
        logging.error(f"Ошибка при удалении {target}: {e}")

def cleanup_directory(config: dict):
    """Очищает директорию по конфигу"""
    base_dir = Path(config["path"])
    if not base_dir.exists():
        logging.warning(f"Директория не найдена: {base_dir}")
        return

    # Проверка, не в блоклисте ли мы
    if any(blocked in base_dir.parents for blocked in BLOCKLIST):
        logging.error(f"Попытка очистки защищенной директории: {base_dir}. Прерывание.")
        return

    current_time = time.time()
    for pattern in config["patterns"]:
        for target in base_dir.rglob(pattern):  # Рекурсивный поиск по шаблону
            if not target.exists():
                continue

            # Проверка возраста файла/папки
            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("=== Запуск очистки ===")
    for job in TARGETS:
        cleanup_directory(job)
    logging.info("=== Очистка завершена ===\n")

Сравнительный анализ

Где ChatGPT был прав:

  1. Максимально обезопасил скрипт. Исключил подобные rm -rf прямые вызовы, используя встроенные методы Python (unlink, rmdir). Появился BLOCKLIST, который полностью запрещает любые попытки залезть в / или $HOME.

  2. Добавил настраиваемость. Вместо хардкода — хороший конфиг в виде списка словарей TARGETS. Необходимо почистить другую папку или поменять «возраст»? Просто редактируется список без изменения кода. На мой взгляд, правильное и грамотное решение.

  3. Скрипт теперь ведёт полноценный лог-файл. Теперь видно не только что удалили, но и почему что-то идёт не так.

  4. Использование pathlib.Path вместо склеивания строк, что является более корректной работой с путями. Он автоматически обрабатывает разные ОС и экранирует спецсимволы.

Где ChatGPT был не совсем прав (на мой взгляд, поправьте, пожалуйста, если ошибаюсь):

  1. Немного опасный рекурсивный поиск. Изначально ИИ использовал base_dir.rglob('*') для паттерна "*" в ~/.cache. Это буквально значит: "иди рекурсивно по ВСЕМУ в кэше и проверяй возраст КАЖДОГО файла". Для директории кэша, где огромное множество мелких файлов, это вполне могло привести к невероятно долгой и бесполезной работе. Я бы добавил условие на минимальный возраст для столь агрессивной очистки.

  2. Имитация безопасности. Функция safe_remove пытается удалить папку только в случае, если она пуста. Это безопасно, но полностью бесполезно для забитых до потолка node_modules. Для «непустых» директорий, скрипт просто проигнорирует их. Стоило бы явно указать это в логировании.

  3. Не самые практичные шаблоны. Шаблон "*" для ~/.cache слишком широкий. Правильнее было бы: ['*.bin', 'cache/*', 'thumbnails/*'] и т.д.

Какой итог можно вывести: ChatGPT сделал из некачественного и немного опасного bash‑скрипта — почти продакшен утилиту с конфигом и логами. Но, слепая уверенность в рекурсивном обходе «всего и вся» могла легко подвесить систему. ИИ отлично структурирует и обезопашивает код, но ему словно не хватает предметного понимания «что именно мне чистить?». Как вспомогательный инструмент для генерации — незаменимая вещь, но надо хорошо знать материал и очень внимательно следить за генерируемым кодом, дабы избегать опасных последствий.

Я попросил DeepSeek оценить статью и меня опять отчитали...

Сделать решил ради интереса, буквально за 5-10 минут перед публикацией. Что из этого вышло:

Где ChatGPT был не совсем прав (Ваши замечания и мои дополнения)

Вы абсолютно правы в своих опасениях, и они касаются фундаментальных проблем генеративного ИИ.

  1. Опасный рекурсивный поиск (rglob('*')). Это не просто "немного опасно", это катастрофически неэффективно для таких директорий, как ~/.cache или node_modules. ИИ не думает о производительности и последствиях в реальной системе. Он видит шаблон * и механически применяет к нему rglob. В реальности это вызовет:

    • Чудовищную нагрузку на I/O (тысячи и даже миллионы системных вызовов stat).

    • Долгое время выполнения.

    • Возможное исчерпание лимита на количество открытых файлов (особенно в больших node_modules).

    Решение: Для таких случаев нужна не рекурсия с проверкой каждого файла, а агрессивное удаление целых поддиректорий кэша (например, ~/.cache/thumbnails/~/.cache/mozilla/) по истечении срока их жизни, используя shutil.rmtree() (с огромной осторожностью!) или специализированные утилиты вроде apt-get cleanyay -Sccnpm cache clean --force.

  2. Имитация безопасности (rmdir для пустых папок). Это не недостаток, а скорее следствие первого пункта. ИИ выбрал безопасный, но бесполезный метод, потому что он в принципе не стал предлагать удаление непустых директорий — это слишком опасно для генерации без явного указания. Он сыграл в перестраховку. Для реальной задачи очистки кэшей и node_modules этот подход действительно бесполезен.

  3. Широкие шаблоны. Согласен. ИИ работает в отрыве от контекста реальных систем. Он не знает типичную структуру ~/.cache/ в Linux или ~/Library/Caches/ в macOS. Его шаблоны общие и абстрактные.

Критическая ошибка, которую вы, возможно, не заметили

В вашем исправленном коде есть одна крайне опасная строка, которая полностью обнуляет весь смысл BLOCKLIST:

if any(blocked in base_dir.parents for blocked in BLOCKLIST):

Проблема: Эта проверка происходит только для base_dir (корневой директории цели, например, ~/Downloads). Она не проверяет каждый найденный файл (target) на вхождение в блоклист.

Сценарий катастрофы:

  1. Вы по неосторожности добавляете в TARGETS цель { "path": "/" } (или ИИ делает это по вашему запросу).

  2. Скрипт проверяет: "/" in Path("/").parents? Нет, потому что Path("/").parents пуст. Проверка проходит.

  3. Скрипт начинает рекурсивно обходить всю файловую систему (rglob('*') от корня!) и удалять все файлы старше N дней.

  4. Ваша система уничтожена.

Правильное решение: Проверку на блоклист нужно делать для каждого найденного файла/директории (target) внутри safe_remove, прежде чем что-либо с ним делать.

Пример использования

По классике, инструкция к скрипту в статье (может кому-то понадобится?):

  1. Сохраняем код в файл cleanup_agent.py.

  2. Редактируем конфиг TARGETS под нужные задачи. Необходимо чистить Downloads раз в неделю - пожалуйста. Стоит почистить Projects от pycache - добавляем правило.

  3. Запускаем и смотрим логи.

# Делаем скрипт исполняемым
chmod +x cleanup_agent.py

# Запускаем
python3 cleanup_agent.py

# Смотрим, что он наснимал
tail -f ~/cleanup_agent.log

Вывод в логе будет примерно таким:

2025-08-19 11:05:32,123 - INFO - === Запуск очистки ===
2025-08-19 11:05:32,456 - INFO - Удален файл: /home/user/Downloads/old_report.tmp
2025-08-19 11:05:33,001 - ERROR - Ошибка при удалении /home/user/.cache/some_file: [Errno 13] Permission denied
2025-08-19 11:05:33,002 - INFO - === Очистка завершена ===

Итог

Мой небольшой эксперимент по переводу убогого bash-скрипта в элегантный Python-инструмент с помощью ChatGPT оказался крайне показательным. Вот ключевые выводы, к которым я пришёл:

  1. ИИ - практически гениальный архитектор, но немного плохой предметный эксперт. ChatGPT блестяще справился со структурой: предложил конфиг, модульную архитектуру, логирование и, что я считаю наиболее ценным — механизмы безопасности (пусть в bash они и отсутствуют вовсе). Но, предметное знание оставляет желать лучшего: рекурсивный обход всего содержимого .cache — верный путь к бесполезному простою скрипта. ИИ не понимает контекста и типичного содержания папок в отличие от системного администратора или разработчика.

  2. Одним из главных достижений ИИ считаю внедрение BLOCKLIST. ИИ‑модель, обученная на миллионах строк кода, интуитивно понимает, что является опасным, поэтому интуитивно предлагает встроенные защитные механизмы. Это крайне ценно, особенно для новичков, которые могут не осознавать всей деструктивности своих решений (что и показывает пример с одним из первых моих скриптов).

  3. ИИ определенно точно повышает «уровень» кода, но никогда не заменит мышление. Да, он превратил мой «костыль» в читаемый и поддерживаемый код, но финальный вариант потребовал моей ревизии. Пришлось анализировать предложенное решение, изучить потенциальные узкие места и вносить корректировки (я всё ещё не доверяю ИИ). В итоге получается, что ChatGPT — сильный усилитель компетенций, но никак не замена. Без знаний не получиться правильно оценить результат, что иногда может быть фатальным.

  4. Факт того, что ИИ сразу предложил Python вместо Bash — весьма интересно. Он понял, что задача вышла за рамки простой автоматизации (Bash) в область создания чего‑то более надёжного и безопасного, где Bash был бы лишь помехой.

Также, вопрос к Вам. Доверяете ли Вы ИИ писать системные скрипты? Если нет, то почему?

P. S. В моей группе в Телеграмм разбираем практические кейсы: скрипты (Python/Bash/PowerShell), тонкости ОС и инструменты для эффективной работы.

Комментарии (11)


  1. vanton
    20.08.2025 14:35

    Для удаления старых папок node_modules и подобных - есть замечательная утилита npx npkill


    1. eternaladm Автор
      20.08.2025 14:35

      Спасибо за комментарий! Прекрасно знаком, с опытом пришло. Представленный в статье bash-скрипт - начало моего знакомства со скриптами, когда я в целом почти не был осведомлен о существовании каких-либо утилит. Вроде упомянул в начале...


  1. bolk
    20.08.2025 14:35

    `find ~ \( -name '*.log' -o -name '*.tmp' \) -mtime +30 -delete 2>&-`


  1. PitAlex
    20.08.2025 14:35

    Он понял, что задача вышла за рамки простой автоматизации (Bash)
    Bash — не подходящий для задачи инструмент
    повеселился, для этой задачи ничего больше и не нужно


    1. eternaladm Автор
      20.08.2025 14:35

      Спасибо за комментарий! Я с Вами не спорю, абсолютно верно, для задачи "удалить файлы по паттерну" Bash`а будет предостаточно.

      Мой вывод был не в том, что Bash не справится, а скорее о том, что для создания "безопасного и настраиваемого инструмента" выберет ИИ и как он это реализует. Я не гнался за идеей о том, что все решения в статье - исключительно мои и исключительно верные.

      ИИ часто выбирают именно Python, как основное решение. Это не мой выбор. И в чем-то я согласен, Python как "постоянное и поддерживаемое" решение будет более гибок.


      1. PitAlex
        20.08.2025 14:35

        для создания "безопасного и настраиваемого инструмента"

        безопасность и настройки зависят от реализации а не от инструмента

        Python как "постоянное и поддерживаемое" решение

        bash - стар, bash - очень стар, BASH - SUPER STAR

        bash - жил, bash - жив, bash - будет жить
        :-) :-) :-) :-) :-) :-) :-) :-) :-)

        ИМХО - ИИ гораздо проще найти решение на более "популярном" языке, хотелось бы посмотреть решение от ИИ имеено на bash

        /


        1. eternaladm Автор
          20.08.2025 14:35

          безопасность и настройки зависят от реализации а не от инструмента

          Есть предположение, что сообщать это надо ИИ. Я не преследовал цель запросить полный аналог, задумка - посмотреть реализацию и сравнить подходы. В момент написания моего скрипта я не выбрал Python, ИИ - наоборот.

          bash - стар, bash - очень стар, BASH - SUPER STAR

          Нигде в своих тезисах я не высказывался о бессмысленности Bash, он всё ещё остается фундаментальной базой, некий "мастодонт" администрирования.

          Возможно я плохо донёс основную цель, миссию, идею статьи...

          Специально для Вас, дополнение к статье (спойлер, скрипт 230 строк). Заранее скажу, никакие правки не вносил, исключительно перевёл на русский для удобства:

          Версия скрипта от ChatGPT
          #!/bin/bash
          
          # Безопасный скрипт очистки системы
          # Конфигурируемая и безопасная очистка файлов/директорий с логированием и защитой
          
          set -euo pipefail  # Строгая обработка ошибок
          
          # Конфигурация
          readonly CONFIG_FILE="${HOME}/.cleanup_config"
          readonly LOG_FILE="${HOME}/cleanup.log"
          readonly DEFAULT_DRY_RUN=true
          readonly DEFAULT_MAX_AGE_DAYS=30
          
          # Заблокированные опасные директории (абсолютные пути)
          readonly BLOCKLIST=(
              "/"
              "/home"
              "/etc"
              "/var"
              "/usr"
              "/bin"
              "/sbin"
              "/lib"
              "/lib64"
              "/boot"
              "/root"
              "/proc"
              "/sys"
              "/dev"
              "/mnt"
              "/media"
          )
          
          # Загрузка конфигурации или использование значений по умолчанию
          load_config() {
              local dry_run="$DEFAULT_DRY_RUN"
              local max_age_days="$DEFAULT_MAX_AGE_DAYS"
              local -a target_dirs=()
              local -a file_patterns=()
          
              if [[ -f "$CONFIG_FILE" ]]; then
                  # Безопасная загрузка конфигурации
                  while IFS= read -r line || [[ -n "$line" ]]; do
                      line="${line%%#*}"  # Удаляем комментарии
                      line="${line##*( )}"  # Обрезаем начальные пробелы
                      line="${line%%*( )}"  # Обрезаем конечные пробелы
                      
                      case "$line" in
                          dry_run=*)
                              dry_run="${line#dry_run=}"
                              ;;
                          max_age_days=*)
                              max_age_days="${line#max_age_days=}"
                              ;;
                          target_dir=*)
                              local dir="${line#target_dir=}"
                              if [[ -n "$dir" ]]; then
                                  target_dirs+=("$dir")
                              fi
                              ;;
                          file_pattern=*)
                              local pattern="${line#file_pattern=}"
                              if [[ -n "$pattern" ]]; then
                                  file_patterns+=("$pattern")
                              fi
                              ;;
                      esac
                  done < "$CONFIG_FILE"
              else
                  # Цели по умолчанию если конфиг отсутствует
                  target_dirs=(
                      "${HOME}/cache"
                      "${HOME}/.cache"
                      "${HOME}/tmp"
                      "${HOME}/.tmp"
                  )
                  file_patterns=(
                      "*.log"
                      "*.tmp"
                      "*.temp"
                      "*.cache"
                  )
              fi
          
              echo "$dry_run:$max_age_days:${target_dirs[*]}:${file_patterns[*]}"
          }
          
          # Проверка безопасности пути
          is_safe_path() {
              local path="$1"
              
              # Проверяем абсолютный путь и отсутствие в блоклисте
              for blocked in "${BLOCKLIST[@]}"; do
                  if [[ "$path" == "$blocked" || "$path" == "$blocked/"* ]]; then
                      log_message "БЛОКИРОВКА" "Попытка доступа к заблокированной директории: $path"
                      return 1
                  fi
              done
          
              # Дополнительные проверки безопасности
              if [[ ! "$path" =~ ^/ ]]; then
                  log_message "ОШИБКА" "Относительные пути запрещены: $path"
                  return 1
              fi
          
              if [[ "$path" == "/"* && ! "$path" =~ ^${HOME} ]]; then
                  log_message "ПРЕДУПРЕЖДЕНИЕ" "Путь вне домашней директории: $path"
                  # Требуем явного подтверждения для системных путей
                  [[ "${DRY_RUN:-true}" == "true" ]] && return 0
                  read -p "Разрешить очистку системного пути $path? (y/Н): " -n 1 -r
                  echo
                  [[ $REPLY =~ ^[Yy]$ ]] || return 1
              fi
          
              return 0
          }
          
          # Безопасное расширение директорий с glob-шаблонами
          expand_directories() {
              local -a directories=()
              
              for pattern in "$@"; do
                  if [[ "$pattern" == *"*"* ]]; then
                      # Обрабатываем glob-шаблоны безопасно
                      while IFS= read -r -d '' dir; do
                          if is_safe_path "$dir"; then
                              directories+=("$dir")
                          fi
                      done < <(find . -maxdepth 2 -path "$pattern" -type d -print0 2>/dev/null | head -n 50)
                  else
                      # Обычная директория
                      if is_safe_path "$pattern" && [[ -d "$pattern" ]]; then
                          directories+=("$pattern")
                      fi
                  fi
              done
          
              printf '%s\n' "${directories[@]}"
          }
          
          # Функция логирования
          log_message() {
              local level="$1"
              local message="$2"
              local timestamp
              timestamp=$(date '+%Y-%m-%d %H:%M:%S')
              
              echo "[$timestamp] [$level] $message" | tee -a "$LOG_FILE"
          }
          
          # Безопасное удаление
          safe_remove() {
              local path="$1"
              local max_age="${2:-0}"
              local find_cmd=()
          
              if ! is_safe_path "$path"; then
                  return 1
              fi
          
              if [[ "$max_age" -gt 0 ]]; then
                  find_cmd=(find "$path" -type f -mtime "+$max_age" -print0)
              else
                  find_cmd=(find "$path" -print0)
              fi
          
              if [[ "${DRY_RUN:-true}" == "true" ]]; then
                  log_message "ТЕСТОВЫЙ_РЕЖИМ" "Будет удалено: $path"
                  "${find_cmd[@]}" | xargs -0 -I{} echo "Будет удалено: {}" | head -n 10 | tee -a "$LOG_FILE"
              else
                  log_message "УДАЛЕНИЕ" "Удаляем: $path"
                  "${find_cmd[@]}" | xargs -0 -I{} sh -c '
                      echo "Удаляем: $1"
                      rm -rf -- "$1"
                  ' sh {} | head -n 10 | tee -a "$LOG_FILE"
              fi
          }
          
          # Основная функция очистки
          main() {
              local dry_run max_age_days
              local -a target_dirs file_patterns
          
              # Парсим конфигурацию
              IFS=':' read -r dry_run max_age_days _ _ < <(load_config)
              IFS=' ' read -r -a target_dirs < <(load_config | cut -d: -f3)
              IFS=' ' read -r -a file_patterns < <(load_config | cut -d: -f4)
          
              DRY_RUN="${dry_run}"
              MAX_AGE_DAYS="${max_age_days}"
          
              log_message "ИНФО" "Начало очистки (Тестовый режим: $DRY_RUN, Макс. возраст: ${MAX_AGE_DAYS} дней)"
          
              # Очищаем конкретные директории
              for dir in "${target_dirs[@]}"; do
                  if [[ -n "$dir" ]]; then
                      expanded_dirs=$(expand_directories "$dir")
                      if [[ -n "$expanded_dirs" ]]; then
                          while IFS= read -r expanded_dir; do
                              safe_remove "$expanded_dir" 0
                          done <<< "$expanded_dirs"
                      fi
                  fi
              done
          
              # Очищаем файлы по шаблону
              for pattern in "${file_patterns[@]}"; do
                  if [[ -n "$pattern" ]]; then
                      log_message "ИНФО" "Очищаем файлы по шаблону: $pattern"
                      find ~ -name "$pattern" -mtime "+${MAX_AGE_DAYS}" -type f -print0 2>/dev/null | \
                      while IFS= read -r -d '' file; do
                          if is_safe_path "$file"; then
                              if [[ "$DRY_RUN" == "true" ]]; then
                                  log_message "ТЕСТОВЫЙ_РЕЖИМ" "Будет удален файл: $file"
                              else
                                  log_message "УДАЛЕНИЕ" "Удаляем файл: $file"
                                  rm -f -- "$file"
                              fi
                          fi
                      done
                  fi
              done
          
              log_message "ИНФО" "Очистка завершена успешно"
          }
          
          # Обработка сигналов
          trap 'log_message "ОШИБКА" "Скрипт прерван пользователем"; exit 1' INT TERM
          
          # Запускаем основную функцию
          main "$@"

          А также, меня обрадовали конфигом:

          # Конфигурация очистки
          dry_run=false
          max_age_days=30
          
          # Директории для очистки
          target_dir=~/cache
          target_dir=~/projects/*/node_modules
          target_dir=~/.npm_cache
          
          # Шаблоны файлов для очистки
          file_pattern=*.log
          file_pattern=*.tmp
          file_pattern=*.temp
          file_pattern=*.cache


  1. select26
    20.08.2025 14:35

    chmod +x cleanup_agent.py

    # Запускаем
    python3 cleanup_agent.py

    Зачем делать chmod, если вы запускаете скрипт параметром интерпретатора?

    Тогда уж добавьте шебанг и запускайте непосредственно скрипт, а не интерпретатор.

    И вообще - ваша статья это хорошее подтверждение, что все LLM никуда не годны для разработки.


    1. eternaladm Автор
      20.08.2025 14:35

      Спасибо за комментарий и недочёт! В статье уже исправил, написал "по привычке", не вдумался...


      1. Dartess
        20.08.2025 14:35

        не вдумался

        иронично в контексте статьи


        1. eternaladm Автор
          20.08.2025 14:35

          Спасибо за комментарий! Как раз хотел подметить, достаточно забавно)

          На самом деле, действительно не люблю за подобные "побочные эффекты" пользоваться ИИ...