Методы поиска файлов и директорий в 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)
В сетевых файловых системах возможны временные ошибки. Повторные попытки с задержкой увеличивают надёжность.