🏠 Домашнее задание

⚡ Суть задания

Домашнее задание состоит из двух задач: вывести отдельно папки и файлы заданной директории, а также рекурсивно найти и при подтверждении удалить файлы с заданным расширением.

Результат: два скрипта, запускаемые из командной строки с аргументами.

📋 Формулировка задания

Исходное задание из LMS:

  1. Список файлов и папок
    Напишите программу, которая принимает путь к директории через аргумент командной строки и выводит отдельно список папок и отдельно список файлов.
    Пример запуска:
    python script.py /home/user/documents
    Пример вывода:
    Содержимое директории '/home/user/documents':
    Папки:
    - folder1
    - folder2
    Файлы:
    - file1.txt
    - file2.txt
    - notes.docx
  2. Поиск и удаление файлов с указанным расширением
    Напишите программу, которая:
    • принимает путь к директории и расширение файлов через аргументы командной строки;
    • рекурсивно ищет файлы с этим расширением во всех вложенных папках;
    • спрашивает у пользователя, хочет ли он удалить найденные файлы;
    • если пользователь подтверждает, удаляет их.
    Пример запуска:
    python script.py /home/user/PycharmProjects/project1 .log
    Пример вывода:
    Найдены файлы с расширением '.log':
    - logs/error.log
    - logs/system.log
    - logs/backup/old.log
    - logs/backup/debug.log
    Вы хотите удалить эти файлы? (y/n): y
    Удаление завершено.

🔧 Шаг 0. Подготовка окружения

Перед началом работы над любым заданием курса нужно настроить окружение. Эти шаги одинаковы для всех уроков.

📁 Структура репозитория: мы используем один репозиторий для всех практических работ курса. Это удобнее, чем много отдельных репозиториев: общий .gitignore, единая история, легко переключаться между уроками.
1

Создайте (или откройте) рабочую папку

В VS Code нажмите Ctrl+K Ctrl+O → выберите или создайте папку python-fundamentals-practice. Это будет корень вашего учебного репозитория.

# Или в терминале VS Code (Ctrl + `):
mkdir python-fundamentals-practice
cd python-fundamentals-practice
2

Инициализируйте Git-репозиторий (один раз)

Если папка ещё не является git-репозиторием:

git init

# Создайте базовые файлы
echo "# Python Fundamentals — Практические работы" > README.md
echo "venv/" > .gitignore
echo "__pycache__/" >> .gitignore
echo "*.pyc" >> .gitignore
echo ".env" >> .gitignore
echo "*.log" >> .gitignore

git add README.md .gitignore
git commit -m "init: базовая структура репозитория"
3

Создайте папку для текущего урока

# Структура: lesson-XX/
mkdir -p lesson-50
cd lesson-50
4

Создайте виртуальное окружение (venv)

# Windows (PowerShell / CMD)
python -m venv venv
venv\Scripts\activate

# Mac / Linux
python3 -m venv venv
source venv/bin/activate

После активации в начале строки терминала появится (venv). Все дальнейшие команды выполняйте внутри venv.

5

Создайте ветку для задания

# Вернитесь в корень репозитория
cd ../..

# Создайте и переключитесь на ветку
git checkout -b lesson/50-file-system

# Отправьте ветку на удалённый репозиторий (если настроен)
git push -u origin lesson/50-file-system

Именование веток: lesson/XX-краткое-название. Это позволяет легко находить нужный урок.

🛠️ Шаги выполнения задания

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

1

Шаг 1: список файлов и папок

Создайте файл list_dirs_and_files.py и реализуйте разделение содержимого директории.

# list_dirs_and_files.py
import os
import sys


def main():
    if len(sys.argv) != 2:
        print("Использование: python list_dirs_and_files.py <директория>")
        sys.exit(1)

    directory = sys.argv[1]

    if not os.path.isdir(directory):
        print(f"Директория '{directory}' не существует.")
        sys.exit(1)

    folders = []
    files = []

    for item in os.listdir(directory):
        item_path = os.path.join(directory, item)
        if os.path.isdir(item_path):
            folders.append(item)
        elif os.path.isfile(item_path):
            files.append(item)

    print(f"Содержимое директории '{directory}':")
    print("Папки:")
    for folder in folders:
        print(f"- {folder}")
    print("Файлы:")
    for file in files:
        print(f"- {file}")


if __name__ == "__main__":
    main()

Проверка в VS Code:

  1. Убедитесь, что venv активирован.
  2. Создайте тестовую папку, например test_data, и поместите в неё несколько файлов и подпапок.
  3. Запустите: python list_dirs_and_files.py test_data
  4. Убедитесь, что папки и файлы выводятся в отдельных списках.
2

Шаг 2: поиск и удаление файлов по расширению

Создайте файл find_and_delete_by_extension.py. Программа должна рекурсивно искать файлы, спрашивать подтверждение и удалять их.

# find_and_delete_by_extension.py
import os
import sys


def main():
    if len(sys.argv) != 3:
        print("Использование: python find_and_delete_by_extension.py <директория> <расширение>")
        sys.exit(1)

    directory = sys.argv[1]
    extension = sys.argv[2]

    if not os.path.isdir(directory):
        print(f"Директория '{directory}' не существует.")
        sys.exit(1)

    found = []
    for root, dirs, files in os.walk(directory):
        for file in files:
            if file.endswith(extension):
                full_path = os.path.join(root, file)
                relative_path = os.path.relpath(full_path, directory)
                found.append((relative_path, full_path))

    if not found:
        print(f"Файлы с расширением '{extension}' не найдены.")
        return

    print(f"Найдены файлы с расширением '{extension}':")
    for relative_path, _ in found:
        print(f"- {relative_path}")

    answer = input("Вы хотите удалить эти файлы? (y/n): ")
    if answer.strip().lower() == "y":
        for _, full_path in found:
            os.remove(full_path)
        print("Удаление завершено.")
    else:
        print("Удаление отменено.")


if __name__ == "__main__":
    main()

Проверка в VS Code:

  1. Создайте тестовую папку с вложенными подпапками и файлами, например .log.
  2. Запустите: python find_and_delete_by_extension.py test_data .log
  3. Проверьте, что найдены все файлы, включая вложенные.
  4. Введите n — файлы должны остаться на месте.
  5. Запустите снова, введите y — файлы должны удалиться.

✅ Полное решение

Ниже приведены оба файла в финальном виде. Совет: попробуйте выполнить задание самостоятельно, прежде чем смотреть ответ.

# list_dirs_and_files.py
import os
import sys


def main():
    if len(sys.argv) != 2:
        print("Использование: python list_dirs_and_files.py <директория>")
        sys.exit(1)

    directory = sys.argv[1]

    if not os.path.isdir(directory):
        print(f"Директория '{directory}' не существует.")
        sys.exit(1)

    folders = []
    files = []

    for item in os.listdir(directory):
        item_path = os.path.join(directory, item)
        if os.path.isdir(item_path):
            folders.append(item)
        elif os.path.isfile(item_path):
            files.append(item)

    print(f"Содержимое директории '{directory}':")
    print("Папки:")
    for folder in folders:
        print(f"- {folder}")
    print("Файлы:")
    for file in files:
        print(f"- {file}")


if __name__ == "__main__":
    main()
# find_and_delete_by_extension.py
import os
import sys


def main():
    if len(sys.argv) != 3:
        print("Использование: python find_and_delete_by_extension.py <директория> <расширение>")
        sys.exit(1)

    directory = sys.argv[1]
    extension = sys.argv[2]

    if not os.path.isdir(directory):
        print(f"Директория '{directory}' не существует.")
        sys.exit(1)

    found = []
    for root, dirs, files in os.walk(directory):
        for file in files:
            if file.endswith(extension):
                full_path = os.path.join(root, file)
                relative_path = os.path.relpath(full_path, directory)
                found.append((relative_path, full_path))

    if not found:
        print(f"Файлы с расширением '{extension}' не найдены.")
        return

    print(f"Найдены файлы с расширением '{extension}':")
    for relative_path, _ in found:
        print(f"- {relative_path}")

    answer = input("Вы хотите удалить эти файлы? (y/n): ")
    if answer.strip().lower() == "y":
        for _, full_path in found:
            os.remove(full_path)
        print("Удаление завершено.")
    else:
        print("Удаление отменено.")


if __name__ == "__main__":
    main()

🧪 Как проверить решение

  1. Активируйте venv: venv\Scripts\activate (Windows) или source venv/bin/activate (Mac/Linux).
  2. Для первой задачи запустите: python list_dirs_and_files.py <путь_к_папке>. Убедитесь, что папки и файлы выводятся отдельно.
  3. Для второй задачи запустите: python find_and_delete_by_extension.py <путь_к_папке> .log.
    • Проверьте поиск вложенных файлов.
    • Проверьте отмену удаления (ввод n).
    • Проверьте подтверждение удаления (ввод y).

🐛 Отладка в VS Code

Если что-то не работает:

  1. Поставьте точку останова (breakpoint) на строке, где читается sys.argv.
  2. Нажмите F5 или выберите «Run → Start Debugging».
  3. На панели Debug следите за значениями переменных directory и extension.
  4. Если программа пишет, что директория не найдена, проверьте, что путь существует и вы запускаете скрипт из правильной папки.
  5. Для задачи с удалением используйте тестовую копию данных, чтобы случайно не удалить важные файлы.

💾 Сохранение работы

# Добавьте файлы урока
git add lesson-50/

# Сделайте коммит с осмысленным сообщением
git commit -m "lesson-50: работа с файловой системой"

# Отправьте на GitHub / GitLab
git push

💡 Советы и типичные ошибки

  • Не забывайте, что sys.argv[0] — имя скрипта, а пользовательские аргументы начинаются с sys.argv[1].
  • Используйте os.path.join для сборки путей, чтобы код работал на Windows, Linux и macOS.
  • Для удаления непустых директорий os.rmdir не подходит — используйте его только для пустых папок.
  • Всегда спрашивайте подтверждение перед удалением файлов, особенно при рекурсивном поиске.
  • Не коммитьте папку venv/ и временные файлы — они указаны в .gitignore.