Следуйте инструкциям в видео ниже, чтобы узнать, как установить наш сайт как веб-приложение на главный экран вашего устройства.
Примечание: Эта функция может быть недоступна в некоторых браузерах.
Вы используете устаревший браузер. Этот и другие сайты могут отображаться в нём неправильно. Необходимо обновить браузер или попробовать использовать другой.
У каждого из нас в какой-либо из папок скапливается большое количество файлов, рассортировать которые все никак не доходят руки. Мне приходилось наблюдать папку «Загрузки» забитую неимоверным количеством файлов, «Рабочие столы», фото на которых лежит почти друг на друге. И у меня иногда скапливаются файлы, на сортировку которых уходит время. А что, если написать небольшой скрипт на Python, который рассортирует файлы по расширениям и разложит по папкам, попутно удалив пустые директории автоматически? Давайте сделаем это.
Думаю, что не сделаю никаких открытий, сказав, что рассортировать файлы можно с использованием одной библиотеки pathlib, а точнее, ее модуля Path. Каюсь, до недавнего времени, почему-то не обращал на эту библиотеку должного внимания. Может быть потому, что она не представляет из себя ничего экзотического. Но, вот попалась она мне на глаза и попробовав с ней работать я понял, насколько это удобнее, когда идет работа с файлами, чем использовать модуль os. С помощью данного модуля можно получить как полный путь к файлу, так и его расширение, имя, просто путь к папке с файлом и многое другое. А также выполнять базовые операции по удалению, переименованию и перемещению файлов.
Данная заметка, это скорее пример использования данного модуля в практических целях. Ну и кто знает, может быть данный код будет кому-нибудь полезен.
Что потребуется?
Для того, чтобы написать данный скрипт не потребуется скачивать никаких сторонних библиотек, так как библиотека pathlib является предустановленной вместе с Python. Поэтому, нам нужно ее только импортировать в наш скрипт.
from pathlib import Path
Создаем словарь с названиями директорий и расширениями привязанными к ним. Ключом в данном словаре будет название директории, например: «Images», а значением список с расширениями: [".pdf"]. В полном виде данный словарь будет выглядеть вот так:
Конечно же, вы можете самостоятельно добавить директории, а также типы файлов которые нужно будет в них отсортировать. И это, по сути, самая трудоемкая часть данного скрипта.
Теперь создадим функцию, которая на входе будет принимать путь к директории, в которой нужно сортировать файлы. Назову ее: sort_func(path_dir).
Для начала создам переменную, которая будет хранить путь к целевой директории, преобразованной с помощью модуля Path.
Python:
cur_dir = Path(path_dir)
Теперь запускаю цикл по целевой директории, из которой, с помощью функции iterdir() получаю список файлов. В данном случае переменная file будет содержать полный путь к файлу в директории.
Python:
for file in cur_dir.iterdir():
Затем проверяю, является ли объект полученный в цикле папкой, ведь в директории могут содержаться не только файлы. Проверяю размер папки, и если он равен 0, значит она пустая, а следовательно, ее можно удалить. Что и делается с помощью функции rmdir().
Python:
if file.is_dir():
if file.stat().st_size == 0:
file.rmdir()
Запускаю еще один цикл, в котором уже перебираю содержимое созданного ранее словаря с директориями и расширениями. Проверяю, содержится ли расширение файла в директории в списке ключа.
Python:
for suff in dir_suff_dict:
if file.suffix.lower() in dir_suff_dict[suff]:
Если да, создаем директорию с названием ключа. Здесь не требуется проверки на наличие или отсутствие директории. Все дело в ключе exist_ok=True, который позволяет игнорировать исключение FileExistsError возникающее, если директория уже существует. И затем, перемещаю текущий файл в только что созданную директорию, где в качестве пути, куда перемещать файл указывается имя созданной директории объединенное с именем файла, который нужно переместить.
def sort_func(path_dir):
cur_dir = Path(path_dir)
for file in cur_dir.iterdir():
if file.is_dir():
if file.stat().st_size == 0:
file.rmdir()
for suff in dir_suff_dict:
if file.suffix.lower() in dir_suff_dict[suff]:
dir_img = cur_dir / suff
dir_img.mkdir(exist_ok=True)
file.rename(dir_img.joinpath(file.name))
Ну и код для запуска функции. Для начала запрашиваем у пользователя путь к директории для сортировки. Проверяем, существует ли данная директория. Если нет, сообщаем об этом пользователю. Если да, запускаем функцию сортировки, в которую передаем путь к директории. А по окончании сортировки сообщаем об этом пользователю.
Python:
if __name__ == "__main__":
path_d = input('[+] Введите путь к директории для сортировки: ')
if not Path(path_d).exists():
print('[-] Директории не существует')
else:
sort_func(path_d)
print('[!] Сортировка завершена')
Вот в принципе и все. Хочу сказать, что по удобству работы с файлами данная библиотека намного превосходит библиотеку os. Конечно же, это не говорит о том, что она ее полностью заменяет. Но, могу сказать, что если раньше я, можно сказать, мучился, когда мне нужно было получить расширение файла или его имя без расширения, то теперь, сделать это легко и просто. Одно могу сказать точно, на данную библиотеку нужно было обратить внимание еще раньше.
Но, к моему сожалению, не скажу за всех, но в тех видео и книгах для новичков почему-то очень подробно рассматривается библиотека os, а вот упоминание о pathlib я почти не встречал. По крайней мере, не помню об этом. Встречал данную библиотеку в статьях, но почему-то считал ее сторонней.
Ну и демонстрация работы библиотеки. Вот как выглядела директория до сортировки:
А так уже после:
Python:
from pathlib import Path
dir_suff_dict = {"Images": ['.jpg', '.jpeg', '.png', '.gif', '.tiff', '.ico', '.bmp', '.webp', '.svg'],
"Documents": [".md", ".epub", ".txt", ".docx", ".doc", ".ods", ".odt", ".dotx", ".docm", ".dox",
".rvg", ".rtf", ".rtfd", ".wpd", ".xls", ".xlsx", ".ppt", ".pptx", ".csv", ".xml"],
"Archives": [".iso", ".tar", ".gz", ".7z", ".dmg", ".rar", ".zip"],
"Audio": [".aac", ".m4a", ".mp3", "ogg", ".raw", ".wav", ".wma"],
"Video": [".avi", ".flv", ".wmv", ".mov", ".mp4", ".webm", ".vob", ".mpg", ".mpeg", ".3gp"],
"PDF": [".pdf"],
"HTML": [".html", ".htm", ".xhtml"],
"EXE_MSI": [".exe", ".msi"],
"PYTHON": [".py", ".pyw"]}
def sort_func(path_dir):
cur_dir = Path(path_dir)
for file in cur_dir.iterdir():
if file.is_dir():
if file.stat().st_size == 0:
file.rmdir()
for suff in dir_suff_dict:
if file.suffix.lower() in dir_suff_dict[suff]:
dir_img = cur_dir / suff
dir_img.mkdir(exist_ok=True)
file.rename(dir_img.joinpath(file.name))
if __name__ == "__main__":
path_d = input('[+] Введите путь к директории для сортировки: ')
if not Path(path_d).exists():
print('[-] Директории не существует')
else:
sort_func(path_d)
print('[!] Сортировка завершена')
А на этом, пожалуй, все.
Спасибо за внимание. Надеюсь, что данная информация будет вам полезна
Ну так у вас ошибка при попытке удаления папки. Папка не может быть удалена, так как в ней скорее всего содержится файл миниатюр изображений. А значит, она не удалится. Здесь нужно дополнительно условие добавить, что если у файла расширение .thumb (вроде так...) то его нужно удалить. То есть, этот файл не перемещать, а удалить. А после уже удалять папку.
Ну так у вас ошибка при попытке удаления папки. Папка не может быть удалена, так как в ней скорее всего содержится файл миниатюр изображений. А значит, она не удалится. Здесь нужно дополнительно условие добавить, что если у файла расширение .thumb (вроде так...) то его нужно удалить. То есть, этот файл не перемещать, а удалить. А после уже удалять папку.
Мне сложно сказать, почему у вас не удаляется папка. Возможно помимо этого файла в ней есть еще какие-то скрытые. Я попробую у себя смоделировать ситуацию. Не гарантирую, что получиться смоделировать. У меня еще вопрос есть, а у вас эта папка к приложению привязана?
Мне сложно сказать, почему у вас не удаляется папка. Возможно помимо этого файла в ней есть еще какие-то скрытые. Я попробую у себя смоделировать ситуацию. Не гарантирую, что получиться смоделировать. У меня еще вопрос есть, а у вас эта папка к приложению привязана?
нет, у меня есть куча папок(около 3к) с png изображениями, они ни к какой программе не привязаны и скачены из интернета, сами папки из новеллы и возможно это имеет значение, у них в названии есть что-то типа расширения и в каждой папке по одному-три изображения
нет, у меня есть куча папок(около 3к) с png изображениями, они ни к какой программе не привязаны и скачены из интернета, сами папки из новеллы и возможно это имеет значение, у них в названии есть что-то типа расширения и в каждой папке по одному-три изображения
нет, у меня есть куча папок(около 3к) с png изображениями, они ни к какой программе не привязаны и скачены из интернета, сами папки из новеллы и возможно это имеет значение, у них в названии есть что-то типа расширения и в каждой папке по одному-три изображения
Немного переделал код. То, что у папок что-то вроде расширения, роли не играет. Просто Path не обходил все папки рекурсивно. А только указанную папку верхнего уровня. Поэтому пришлось добавить os.walk. Соответственно, вот что получилось:
Python:
import os
from pathlib import Path
dir_suff_dict = {"Images": ['.jpg', '.jpeg', '.png', '.gif', '.tiff', '.ico', '.bmp', '.webp', '.svg'],
"Documents": [".md", ".epub", ".txt", ".docx", ".doc", ".ods", ".odt", ".dotx", ".docm", ".dox",
".rvg", ".rtf", ".rtfd", ".wpd", ".xls", ".xlsx", ".ppt", ".pptx", ".csv", ".xml"],
"Archives": [".iso", ".tar", ".gz", ".7z", ".dmg", ".rar", ".zip"],
"Audio": [".aac", ".m4a", ".mp3", "ogg", ".raw", ".wav", ".wma"],
"Video": [".avi", ".flv", ".wmv", ".mov", ".mp4", ".webm", ".vob", ".mpg", ".mpeg", ".3gp"],
"PDF": [".pdf"],
"HTML": [".html", ".htm", ".xhtml"],
"EXE_MSI": [".exe", ".msi"],
"PYTHON": [".py", ".pyw"]}
def sort_func(path_dir):
cur_dir = Path(path_dir)
dir_path = []
for root, dirs, files in os.walk(path_dir):
for d in dirs:
dir_path.append(os.path.join(root, d))
for file in files:
p_file = Path(root) / file
for suff in dir_suff_dict:
if p_file.suffix.lower() in dir_suff_dict[suff]:
dir_img = cur_dir / suff
dir_img.mkdir(exist_ok=True)
try:
p_file.rename(dir_img.joinpath(p_file.name))
except FileExistsError:
p_file.rename(dir_img.joinpath(f'{p_file.name.split(".")[0]}_c{p_file.suffix}'))
print(f"Возможно дубликат: {p_file.name}")
for dir_p in reversed(dir_path):
if os.path.split(dir_p)[1] in dir_suff_dict or os.stat(dir_p).st_size != 0:
continue
else:
os.rmdir(dir_p)
if __name__ == "__main__":
path_d = input('[+] Введите путь к директории для сортировки: ')
if not Path(path_d).exists():
print('[-] Директории не существует')
else:
sort_func(path_d)
print('[!] Сортировка завершена')
Попробуйте для начала на тестовых файлах, чтобы проверить, как работает. У меня проблем с удалением папок не наблюдалось.
Немного переделал код. То, что у папок что-то вроде расширения, роли не играет. Просто Path не обходил все папки рекурсивно. А только указанную папку верхнего уровня. Поэтому пришлось добавить os.walk. Соответственно, вот что получилось:
Python:
import os
from pathlib import Path
dir_suff_dict = {"Images": ['.jpg', '.jpeg', '.png', '.gif', '.tiff', '.ico', '.bmp', '.webp', '.svg'],
"Documents": [".md", ".epub", ".txt", ".docx", ".doc", ".ods", ".odt", ".dotx", ".docm", ".dox",
".rvg", ".rtf", ".rtfd", ".wpd", ".xls", ".xlsx", ".ppt", ".pptx", ".csv", ".xml"],
"Archives": [".iso", ".tar", ".gz", ".7z", ".dmg", ".rar", ".zip"],
"Audio": [".aac", ".m4a", ".mp3", "ogg", ".raw", ".wav", ".wma"],
"Video": [".avi", ".flv", ".wmv", ".mov", ".mp4", ".webm", ".vob", ".mpg", ".mpeg", ".3gp"],
"PDF": [".pdf"],
"HTML": [".html", ".htm", ".xhtml"],
"EXE_MSI": [".exe", ".msi"],
"PYTHON": [".py", ".pyw"]}
def sort_func(path_dir):
cur_dir = Path(path_dir)
dir_path = []
for root, dirs, files in os.walk(path_dir):
for d in dirs:
dir_path.append(os.path.join(root, d))
for file in files:
p_file = Path(root) / file
for suff in dir_suff_dict:
if p_file.suffix.lower() in dir_suff_dict[suff]:
dir_img = cur_dir / suff
dir_img.mkdir(exist_ok=True)
try:
p_file.rename(dir_img.joinpath(p_file.name))
except FileExistsError:
p_file.rename(dir_img.joinpath(f'{p_file.name.split(".")[0]}_c{p_file.suffix}'))
print(f"Возможно дубликат: {p_file.name}")
for dir_p in reversed(dir_path):
if os.path.split(dir_p)[1] in dir_suff_dict or os.stat(dir_p).st_size != 0:
continue
else:
os.rmdir(dir_p)
if __name__ == "__main__":
path_d = input('[+] Введите путь к директории для сортировки: ')
if not Path(path_d).exists():
print('[-] Директории не существует')
else:
sort_func(path_d)
print('[!] Сортировка завершена')
Попробуйте для начала на тестовых файлах, чтобы проверить, как работает. У меня проблем с удалением папок не наблюдалось.
Добрый день. Вы бы не могли помочь в интеграции в этот код функции нормализации (когда нужно например кириллицу в именах файлов преобразовать в английские буквы) К примеру:
Добрый день. Вы бы не могли помочь в интеграции в этот код функции нормализации (когда нужно например кириллицу в именах файлов преобразовать в английские буквы) К примеру:
Добрый день. Я подумаю, как лучше сделать и отпишусь. Не сразу, так как немного занят, но о результате вам напишу.
Уточняющий вопрос: Если я вас правильно понял, то нужно просто рекурсивно прочитать директорию и переименовать все файлы?
Добрый день. Вы бы не могли помочь в интеграции в этот код функции нормализации (когда нужно например кириллицу в именах файлов преобразовать в английские буквы) К примеру:
import os
import re
from pathlib import Path
def normalize(name: str) -> str:
CYRILLIC_SYMBOLS = 'абвгдеёжзийклмнопрстуфхцчшщъыьэюя'
TRANSLATION = (
"a", "b", "v", "g", "d", "e", "e", "j", "z", "i", "j", "k", "l", "m", "n", "o", "p", "r", "s", "t", "u",
"f", "h", "ts", "ch", "sh", "sch", "", "y", "", "e", "yu", "u", "ja")
TRANS = {}
for c, l in zip(CYRILLIC_SYMBOLS, TRANSLATION):
TRANS[ord(c)] = l
TRANS[ord(c.upper())] = l.upper()
t_name = name.translate(TRANS)
t_name = re.sub(r'\W', '_', t_name)
return t_name
def dir_rename(path: str):
for root, dirs, files in os.walk(path):
for name in files:
path_obj = Path(root) / name
path_obj.rename(Path(root) / f"{normalize(path_obj.name[0:-len(path_obj.suffix)])}{path_obj.suffix}")
def main():
path = input("Введите путь к директории для нормализации: ")
dir_rename(path)
print("Операция завершена")
if __name__ == "__main__":
main()
То есть, для начала, с помощью os.walk рекурсивно считываем содержимое директории. Затем, перебираем полученные файлы и создаем из них объекты Path для того, чтобы можно было ими манипулировать. Затем, переименовываем файл уже в английской раскладке.
То есть, здесь мы для начала узнаем длину расширения файла, так как ее нам переименовывать не нужно, а метод name из Path возвращает имя файла с расширением. split делить не вариант, так как в имени файла могут попасться точки. После чего делаем срез в имени файла, normalize(path_obj.name[0:-len(path_obj.suffix)]), где отсекается расширение, прогоняем через функцию нормализации. И в конце добавляем в f-строке расширение. Для того, чтобы это у нас получился полноценный объект Path, добавляем его в начале.
Вот, в принципе и все. То есть, для примера, с вашей функцией нормализации:
import os
import re
from pathlib import Path
def normalize(name: str) -> str:
CYRILLIC_SYMBOLS = 'абвгдеёжзийклмнопрстуфхцчшщъыьэюя'
TRANSLATION = (
"a", "b", "v", "g", "d", "e", "e", "j", "z", "i", "j", "k", "l", "m", "n", "o", "p", "r", "s", "t", "u",
"f", "h", "ts", "ch", "sh", "sch", "", "y", "", "e", "yu", "u", "ja")
TRANS = {}
for c, l in zip(CYRILLIC_SYMBOLS, TRANSLATION):
TRANS[ord(c)] = l
TRANS[ord(c.upper())] = l.upper()
t_name = name.translate(TRANS)
t_name = re.sub(r'\W', '_', t_name)
return t_name
def dir_rename(path: str):
for root, dirs, files in os.walk(path):
for name in files:
path_obj = Path(root) / name
path_obj.rename(Path(root) / f"{normalize(path_obj.name[0:-len(path_obj.suffix)])}{path_obj.suffix}")
def main():
path = input("Введите путь к директории для нормализации: ")
dir_rename(path)
print("Операция завершена")
if __name__ == "__main__":
main()
То есть, для начала, с помощью os.walk рекурсивно считываем содержимое директории. Затем, перебираем полученные файлы и создаем из них объекты Path для того, чтобы можно было ими манипулировать. Затем, переименовываем файл уже в английской раскладке.
То есть, здесь мы для начала узнаем длину расширения файла, так как ее нам переименовывать не нужно, а метод name из Path возвращает имя файла с расширением. split делить не вариант, так как в имени файла могут попасться точки. После чего делаем срез в имени файла, normalize(path_obj.name[0:-len(path_obj.suffix)]), где отсекается расширение, прогоняем через функцию нормализации. И в конце добавляем в f-строке расширение. Для того, чтобы это у нас получился полноценный объект Path, добавляем его в начале.
Вот, в принципе и все. То есть, для примера, с вашей функцией нормализации:
Спасибо большое за Ваш труд и проделанную работу!! =) Я имел ввиду, в код, который вы писали для сортировки файлов по папкам и расширениям файлов, что бы можно было сделать сортировку файлов по папкам, и расширениям (video, audio, docs и т.д.) и в тоже время прошла функция нормализации для этих файлов. Прошу прощения, что краду ваше время.
Спасибо большое за Ваш труд и проделанную работу!! =) Я имел ввиду, в код, который вы писали для сортировки файлов по папкам и расширениям файлов, что бы можно было сделать сортировку файлов по папкам, и расширениям (video, audio, docs и т.д.) и в тоже время прошла функция нормализации для этих файлов. Прошу прощения, что краду ваше время.
Можно взять тогда код, который я писал в предыдущем ответе и добавить в него нормализацию. Не в самой статье. Там сортировка не рекурсивная. Сейчас гляну.
Спасибо большое за Ваш труд и проделанную работу!! =) Я имел ввиду, в код, который вы писали для сортировки файлов по папкам и расширениям файлов, что бы можно было сделать сортировку файлов по папкам, и расширениям (video, audio, docs и т.д.) и в тоже время прошла функция нормализации для этих файлов. Прошу прощения, что краду ваше время.
На данном сайте используются файлы cookie, чтобы персонализировать контент и сохранить Ваш вход в систему, если Вы зарегистрируетесь. Продолжая использовать этот сайт, Вы соглашаетесь на использование наших файлов cookie.
Комментарии
23