Методы поиска файлов и директорий в Python: от os.path до pathlib

Раздел: Ввод-вывод и файловая система -> Работа с путями файлов

Основные методы поиска пути к файлу или папке

Как проверить, существует ли файл или директория по указанному пути?

Наиболее современный способ — использовать модуль pathlib. Он предоставляет объектно-ориентированный интерфейс для работы с путями, который понятнее и удобнее, чем старый os.path.


from pathlib import Path

path = Path("example.txt")
if path.exists():
    print(f"{path} существует")
else:
    print(f"{path} не найден")

Python find path (поиск пути к файлу или директории в python (os.path, pathlib))

Класс Path автоматически определяет, является ли путь относительным или абсолютным. Метод .exists() возвращает True, если объект файловой системы (файл, директория, ссылка) существует.

Типичная ошибка: передача строки с некорректным разделителем (например, обратная косая черта в Unix). Решение: всегда использовать прямую косую черту или константу os.sep. Pathlib сам нормализует разделители.

Как получить абсолютный путь из относительного?


from pathlib import Path

rel_path = Path("documents/report.txt")
abs_path = rel_path.absolute()
print(abs_path)

Source file python (получение пути к текущему скрипту (source file) в python)

Метод .absolute() добавляет текущий рабочий каталог. Если путь уже абсолютный, он возвращается без изменений.

Ошибка: Path.absolute() не разрешает символические ссылки. Если нужно реальное физическое расположение, используйте .resolve().

Как проверить, ведёт ли путь к файлу или к папке?


p = Path("/usr/bin/python3")
if p.is_file():
    print("Это файл")
elif p.is_dir():
    print("Это папка")
else:
    print("Путь не существует или является специальным объектом")

Python program files path (путь к папке program files в windows из python)

.is_file() и .is_dir() возвращают True только для существующих объектов. Для сломанных символических ссылок оба метода вернут False.

Если нужно разрешить ссылку, сначала вызовите .resolve(), затем проверяйте.

Как найти все файлы с определённым расширением в папке?

from pathlib import Path

base = Path("data")
for file in base.glob("*.csv"):
    print(file.name)

Метод .glob(pattern) возвращает итератор по всем путям, совпадающим с шаблоном (используется синтаксис Unix glob). .rglob(pattern) делает то же самое рекурсивно.

Если шаблон содержит символы, которые могут быть неправильно интерпретированы (например, ?), экранируйте их с помощью .escape() (доступно в Python 3.12+).

Как найти путь к исполняемому файлу в системной переменной PATH?

import shutil

python_path = shutil.which("python3")
print(python_path)

Функция shutil.which() (доступна с Python 3.3) возвращает полный путь к команде, если она найдена в PATH, иначе None.

Обратите внимание: shutil.which() не использует pathlib, но результат можно преобразовать в объект Path: Path(shutil.which('python3')).

Как получить все пути, соответствующие сложному шаблону (например, все логи с датами)?


from pathlib import Path

logs = list(Path("logs").rglob("*.log"))
# Фильтрация вручную
filtered = [p for p in logs if "2024" in p.stem]
print(filtered)

При необходимости можно комбинировать .rglob() с дополнительной фильтрацией по атрибутам пути (имя, расширение, временные метки).

Расширенные примеры поиска путей

1. Рекурсивный поиск с использованием pathlib и обработка ошибок доступа

Пример

from pathlib import Path
import os

def find_large_files(root: str, min_size: int = 10 * 1024 * 1024):
    root_path = Path(root)
    if not root_path.is_dir():
        raise ValueError(f"{root} не является папкой или не существует")
    
    result = []
    for entry in root_path.rglob("*"):
        try:
            if entry.is_file() and entry.stat().st_size >= min_size:
                result.append(entry.absolute())
        except PermissionError:
            # Пропускаем файлы/папки без прав
            continue
    return result

# Пример использования
large = find_large_files("/var/log")
print(f"Найдено {len(large)} больших файлов")
for f in large[:3]:
    print(f)
Найдено 2 больших файла
/var/log/syslog.1
/var/log/kern.log.2.gz

В этом примере используется .rglob("*") для обхода всех элементов рекурсивно. .stat().st_size получает размер файла. Обработка PermissionError позволяет не прерывать поиск.

2. Поиск по имени с использованием регулярных выражений

Пример

import re
from pathlib import Path

def find_by_regex(root: str, pattern: str):
    compiled = re.compile(pattern)
    matches = []
    for path in Path(root).rglob("*"):
        if compiled.search(str(path)):
            matches.append(path)
    return matches

# Найти файлы, содержащие 'backup' или 'archive'
found = find_by_regex("/home/user", r"backup|archive")
for f in found[:5]:
    print(f)
/home/user/backup_2024.zip
/home/user/archive/old_report.pdf

Регулярное выражение применяется к полному строковому представлению пути. Можно модифицировать для поиска только по имени файла, используя path.name.

3. Разрешение символических ссылок и поиск реального расположения

Пример

from pathlib import Path

symlink_path = Path("/usr/local/bin/python3")
if symlink_path.is_symlink():
    real = symlink_path.resolve()
    print(f"Символическая ссылка -> {real}")
else:
    print("Не ссылка")
Символическая ссылка -> /usr/bin/python3.12

.is_symlink() проверяет, является ли объект ссылкой (в Windows это работает для ярлыков .lnk при включенном режиме поддержки). .resolve() возвращает реальный путь, разрешая все цепочки ссылок.

4. Поиск всех путей, содержащих определённый каталог в иерархии

Пример

from pathlib import PureWindowsPath, Path

# Пример для Windows: найти все пути внутри 'AppData\Local'
root = Path("C:/Users/User")
desired_part = PureWindowsPath("AppData/Local")

for entry in root.rglob("*"):
    # Проверяем, содержит ли относительная часть пути 'AppData/Local'
    try:
        rel = entry.relative_to(root)
        if desired_part in rel.parents:
            print(entry)
    except ValueError:
        continue

Используется .relative_to() для получения относительной части, а затем проверяется, входит ли нужная папка в список родителей (.parents — это последовательность всех родительских путей).

5. Поиск самого старого файла в папке

Пример

from pathlib import Path
from datetime import datetime

def oldest_file(directory: str):
    dir_path = Path(directory)
    files = [f for f in dir_path.iterdir() if f.is_file()]
    if not files:
        return None
    oldest = min(files, key=lambda f: f.stat().st_mtime)
    time = datetime.fromtimestamp(oldest.stat().st_mtime)
    return oldest, time

oldest, mtime = oldest_file("/tmp")
print(f"Старейший файл: {oldest}, изменён: {mtime}")
Старейший файл: /tmp/temp_2023_01_01.log, изменён: 2023-01-01 12:00:00

Функция .iterdir() возвращает только прямые дочерние элементы (не рекурсивно). .stat().st_mtime — время последней модификации. Для рекурсивного поиска используйте rglob.

6. Обработка ошибок при поиске (файл удалён во время обхода)

Пример

from pathlib import Path
import time

def safe_find(root: str, pattern: str, max_retries: int = 3):
    root_path = Path(root)
    for attempt in range(max_retries):
        try:
            return list(root_path.glob(pattern))
        except OSError as e:
            if attempt == max_retries - 1:
                raise
            time.sleep(0.5)  # пауза перед повтором
    return []

# Пример: поиск файлов, которые могут быть временно недоступны
result = safe_find("/mnt/nfs", "*.dat")
print(result)

В сетевых файловых системах возможны временные ошибки. Повторные попытки с задержкой увеличивают надёжность.

Поиск пути к файлу или директории в Python (os.path, pathlib) - comments

En
Python find path (python)