Pull to refresh

Comments 37

Вместо os.path.* и прочих лучше использовать pathlib, а вместо range(len(list))enumerate(list).
main_path стоит сделать параметром скрипта.

Спасибо, хорошее замечание. Не использовал библиотеку pathilib, так как никаких сложных манипуляций с путями не производится, только проверка существования файла и парсинг имени файла и расширения.

В связи с потенциально большим количеством файлов в папке, лучше использовать генераторы

О каких генераторах идет речь?

Примерно о таких:


(f.path for f in os.scandir(folder_path) if f.is_dir())
То, что вы назвали генератором — таковым не является. Вы даже в аннотации к функции указали результатом тип list и именно его и возвращаете.
def get_file_paths(folder_path) -> list:
    file_paths = [f.path for f in os.scandir(folder_path) if not f.is_dir()]

    return file_paths

Если бы это действительно было генератором, выглядело бы оно примерно так.
def get_file_paths(folder_path: str) -> Iterator[str]:
    for fn in os.scandir(folder_path):
        if not fn.is_dir():
            yield fn.path


Работать с путями куда проще и правильней при помощи стандартного os.path.join и os.path.split.
Я имел ввиду генератор списка, очевидно. Не особо понимаю, как именно генератор помог бы мне, быстрее бы выполнилась программа? В чем достоинства?
Насчет os.path.join и split согласен.

Меньше памяти. Вместо огромного списка из 100500 строк получаешь небольшой итератор.

for file_path in file_paths:
for p in subfolder_paths:

Как заставить себя придумывать годные имена для переменных? Чтобы не однобуквенные, но немногословные, друг на друга непохожие, осмысленные, и в одном стиле? ;)

Вы обратились явно не по адресу :)
нужно найти какой-то файл. Вот я и подумал, почему бы не написать скрипт сортировщика по расширениям файлов на Python?

Соррян. Так нужно файл найти или отсортировать? Вроде хотели одно, а делаем другое.
У старика Кнута это прям разные главы были. Из того, что я помню, это более эффективный поиск по отсортированной последовательности, но у вас явно не про это.


ЗЫ Вроде в виндоусе есть даже встроенный поиск. Даже я помню вечно тормозящая служба индексера была, да да! Что-то вы странное делаете.

Плохо написал первый абзац, заметил это, но не стал исправлять, так как не нашел более подходящих слов. Я думаю, по заголовку статьи и содержанию можно все-таки понять, что задача именно в сортировке файлов по папкам.
Спасибо, было интересно. А чем не устраивает встроенная в Explorer сортировка? Тоже имею кучу всего в Downloads и по работе периодически приходится что-то оттуда вытаскивать, но для моих целей этого более чем достаточно:
built-in explorer sorting
Решил организовать в едином стиле папки с большим количеством файлов + чуть-чуть покодить
В качестве задачи со звёздочкой можно реализовать в исключительных случаях определение типа файла не по названию расширения, а по каким-нибудь мета-данным. Допустим .ts используется и для исходных файлов языка typescript, и для видеофайлов.
Интересное предложение, реализовывать я его, конечно же, не буду :)
P.S. Вы действительно имели дело с видеофайлами .ts? Я впервые от вас узнал, что такое существует.
Вы действительно имели дело с видеофайлами .ts?

Когда я пропускаю какие-то интересные мне спортивные трансляции по телевизору, то скачиваю записи через торрент. Иногда их выкладывают в формате .ts. Я был и сам удивлён в первый раз, когда только что скачанный файл мне предложили открыть vscodo'м.
Штош. Скорее всего, у многих в папке загрузок собиралась куча разных инсталляторов, архивов и прочих файлов.

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

По тексту статьи она совсем об другой сортировке, сильно специфичной.
Да, если инсталлятор идет не одним файлом, будет грустно. Можно закомментировать в словаре папку exe, как вариант решения проблемы.

Во первых, если в папке Downloads завелись файлы setup.exe, setup(1).exe.., то самый разумный способ автоматической сортировки - Ctrl+A Del. Никто никогда не вспомнит, что это за инсталляторы. Нет смысла их куда то перекладывать.

Во вторых, если было при скачивании лень нажать save as - значит, скачивалось что то одноразовое. Могу предложить отсортировать файлы по дате и удалить все что старше 1 месяца.

эм…
@echo off
ROBOCOPY C:\Users\mf\Downloads\ X:\dl\arch *.zip *.7z *.rar *.gz /MOV /IS /minage:1
ROBOCOPY C:\Users\mf\Downloads\ X:\dl\doc *.doc* *.xls* *.pdf *.csv  /MOV /IS /minage:1
ROBOCOPY C:\Users\mf\Downloads\ X:\dl\img *.psd  /MOV /IS /minage:1
ROBOCOPY C:\Users\mf\Downloads\ X:\dl\soft *.exe *.msi *.cab *.iso *.mdf *.mds  /MOV /IS /minage:1
ROBOCOPY C:\Users\mf\Downloads\ X:\dl\media *.mp3 *.wav *.mp4 *.avi /MOV /IS /minage:1
ROBOCOPY C:\Users\mf\Downloads\ X:\dl\book *.fb2 /MOV /IS /minage:1


а если так? не проще…
Спасибо за хороший метод.
Для конечного потребителя не проще. В скрипте нужно лишь поменять переменную пути каталога и настроить словарь extensions под свой метод сортировки.

В cmd тоже можно использовать переменные ;) А строк получается значительно меньше. Получается, так проще.

Еще раз, для конечного потребителя (обычного юзера, не для энтузиастов с хабра, знающих про ROBOCOPY в cmd) это не проще. Куда легче набрать в текстовом редакторе путь каталога, названия папок и расширения (а можно использовать типовые), чем вот это вот все.
Ваше решение более чем интересное, но, наверное, стоит начать с того. что обычные пользователи пользуются исключительно мышкой и не ходят на Хабр =)

а папка %HOMEPATH%\Downloads обычно является просто свалкой, наравне с %TEMP% и %TMP%

К вашему решению для обычного пользователя осталось добавить gui для настройки и инсталлятор с вэб установщиком интерпретатора.
Они могут сходить на мой ютуб :)

Это слишком длинный путь ;)

Простой способ решения проблемы файлопомойки - сортировка средствами файл менеджера, перенос нужного, удаление ненужного. Написание кода тут совершенно лишнее. :Ь

Хорошо, вы правы.
Извините, что потратил ваше время на чтение этой статьи и написание 4 комментариев

Да я понимаю, что решать разные задачи на питоне это прикольно ;) Но не всегда код на питоне это лучшее решение. И ваша задача - отличная иллюстрация для этого утверждения ;)

Вы никак не угомонитесь, все вас поняли, спасибо. Я зря писал программу.
Решил в лоб, знал про os.listdir и os.scandir. Нужны были пути папок и файлов отдельно. Сделал.
С os.walk не приходилось встречаться, хотя если так подумать, с ним очень просто реализовать многоуровневую сортировку.
Привет. Буквально вчера перебирал file_cache на сервере, папка для временных файлов, которые необходимы пользователям. У нас уже было создано нечто подобное сортировке из статьи. За 6 лет функция обросла многими доработками. Потому расскажу, какие сложности встречались в этой, казалось бы, банальной задаче:

Предпосылки — 100 гигабайт хранилище, 350 000 файлов, расширения png, gif, ico, jpeg, svg, webp, tiff, pdf, tmp, html, xml, xls, xslx, doc, docx, js, css. Видео ни разу не встречал, хоть и можно. И бесконечное количество файлов с .tmp, .temp или без расширений. Адобовские еще файлы какие то AI, PSD… и т.п.

Сложности:
1. Как уже в комментариях сказали — расширение файла не говорит ничего. Хуже того, если отсортировать картинки по расширению, не проверив, для последующей пакетной обработки, например, в PhotoShop или программно в том же PIL — все упадет. Хорошо так упадет.
Для проверки переимовываем xxxxx.jpg в yyyy.png и открываем в photoshop.

В итоге мы стали использовать Fleep автор Mykyta Paliienko. Эта утилита сообщает о типе файла по содержимому. Кстати пришлось доработать «fleeper» до рабочего состояния, в issue автору тоже сообщили.

2. Файлы с именами, написанными через точку, и без расширений. Отдельная задача, поскольку формально расширение есть.

Решилось так же флиппером.

В коде git статьи extension получается через fp.split('.')[-1], это аналог os.path.splitext(fp) и оба не помогут в решении пункта 2, но os.path.splitext более «кошерный» в случае работы с файловой системой.

3. Также в комментариях сказали про однострочные генераторы. Как в статье так и GIT с примером кода, используются листы или функции генераторов, даже там, где достаточно однострочного генератора, который может делать еще и полезную работу:

# функция def sort_files()
for fp, (file, extention) in (fp.path, os.path.splitext(fp.path) for fp in os.scandir(folder_path) if not fp.is_dir()):
....

Если кого расстраивают длинные строки, например линтер black прям беснуется, то можно так же сделать генераторный pipline:
# функция def sort_files()
path_generator = (_file.path for _file in os.scandir(folder_path) if not _file.is_dir())
extentions_generator = (_path, os.path.splitext(_path) for _path in path_generator)
for path, (file, extention) in extentions_generator:
....


4. Создание папок, и, потом, удаление пустых папок — выглядит вычурно. Если есть словарь хранящий { расширение: путь }, тогда проще получать путь из словаря и создавать путь, если словарь вернул пустое значение.

5. Логирование. Сложная тема. Более 300 000 сообщений одномоментно в консоль бессмыслены и ломали «terminus»- консоль в sublime text.

Решение — использовать стандартный логгер Python c выводом в консоль/файл управляя выводом через атрибуты запуска.

Успехов автору в кодинге.
Огромное спасибо за развернутый, конструктивный комментарий.
Sign up to leave a comment.

Articles