Введение


Как человек, который только начинает осваивать Python, я стараюсь получать новые знания и умения путём непосредственной практики. На мой взгляд, данный подход лучше штрудирования гайдов и многотомников по программированию. В первую очередь проектами подобным тому, о котором расскажу, я пытаюсь закрыть свои потребности. На втором месте находится надежда на то, что кому-то ещё может пригодиться то, что я создам (после того, как все имеющиеся ошибки будут исправлены)

Идея данной программы пришла в момент, когда пытался найти ранее загруженный файл среди «помойки», образовавшейся в папке «Загрузки». Изображения, документы, архивы и видео с музыкой: разобраться в этой мешанине и отфильтровать файлы можно было бы конечно, но неохота из-за больших временных затрат. И я подумал о том, что неплохо иметь программу, которая сама разберёт папку «Загрузки» и распределит файлы по стандартным папкам системы «Изображения», «Документы», «Видео» и «Музыка», а ненужные файлы удалит. В итоге на свет появился Perfectionist Organizer, о котором я хотел бы рассказать. Сразу скажу, что это статья от новичка для новичков, потому опытные Python-программисты не найдут здесь ничего полезного (кроме возможности поковыряться в коде и указать на множество ошибок).

Общая идея


Первое, что должна делать программа — определять в какой операционной системе она запущена. Это нужно потому, что в Linux и Windows папка «Загрузки» расположена по разным путям (возможности тестировать программу на Mac у меня нет, потому эту ОС я не учитывал). В обнаруженной папке с загрузками программа перебирает все имеющиеся файлы и определяет к какому типу они относятся (музыка, видео, документы и пр.). После происходит перемещение обнаруженных файлов в дефолтные папки и программа узнаёт у пользователя, что делать с теми файлами, которые не подходят для перемещения — оставить или удалить.

Импорт необходимых библиотек и определение типа системы


Для работы с операционной системой и файлами в ней нам понадобится библиотека os. Библиотека getpass позволит узнать имя пользователя в системе, а platform определит Windows это или Linux. Все нужные библиотеки подключаем в самом начале через import и после определяем тип ОС и имя пользователя.

import os
import getpass
import platform
type_os = platform.system()
usermane = getpass.getuser()

Создание словаря с расширениями популярных файлов и дефолтными папками, которые с ними связаны


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

video_folder = {".3gp" : "Видео/", ".avi" : "Видео/", ".flv" : "Видео/", ".m4v" : "Видео/", ".mkv" : "Видео/", ".mov" : "Видео/", ".mp4" : "Видео/", ".wmv" : "Видео/", ".webm" : "Видео/"}
music_folder = {".mp3" : "Музыка/", ".aac": "Музыка/", ".flac" : "Музыка/", ".mpc" : "Музыка/", ".wma" : "Музыка/", ".wav" : "Музыка/"}
pic_folder = {".raw" : "Изображения/", ".jpg" : "Изображения/", ".tiff" : "Изображения/", ".psd" : "Изображения/", ".bmp" : "Изображения/", ".gif" : "Изображения/", ".png" : "Изображения/", ".jp2" : "Изображения/", ".jpeg" : "Изображения/"}
doc_folder = {".doc" : "Документы/", ".docx" : "Документы/", ".txt" : "Документы/", ".rtf" : "Документы/", ".pdf" : "Документы/", ".fb2" : "Документы/", ".djvu" : "Документы/", ".xls" : "Документы/", ".xlsx" : "Документы/", ".ppt" : "Документы/", ".pptx" : "Документы/", ".mdb" : "Документы/", ".accdb" : "Документы/", ".rar" : "Документы/", ".zip" : "Документы/", ".7z" : "Документы/"}

Не забываем, что после имени папки будет ещё идти имя файла, потому в конце у меня стоит /. Новые типы файлов легко добавляются путём редактирования словаря.

Запрашиваем у пользователя название папки с загрузками


В Windows и Linux папка с загрузками видится в системе с разными названиями. Для Windows это независимо от локализации папка Downloads, тогда на Linux-дистрибутивах эта папка называется «Загрузки». К тому же может произойти так, что пользователь изменил название папки с загруженными файлами и его нужно спросить отличается ли текущее название директории от стандартных.

if type_os == "Linux":
    user_downloads_path = input("Как у вас называется папка с загрузками? (по-умолчанию: Загрузки) ") or "Загрузки"
if type_os == "Windows":
user_downloads_path = input("Как у вас называется папка с загрузками? (по-умолчанию: Загрузки) ") or "Downloads"

Конструкция or позволяет использовать в input значения по-умолчанию. То есть, пользователю в случае если у него нет изменений в имени папки с загрузками, не нужно ничего делать, программа сама подставит нужные значения в дальнейший код.

Устанавливаем путь до папки с загрузками


В зависимости от операционной системы папка с загрузками может находиться в разных местах. Для Linux — это папка расположена по пути /home/имя пользователя/Загрузки/, в Windows же это путь C:/Users/имяпользователя/Downloads/. Чтобы в дальнейшем не прописывать эти пути вручную, проще создать переменные, в которых эти пути будут указаны.

if type_os == "Linux":
    default_path_d = "/home/" + usermane + "/" + user_downloads_path + "/"
else:
    default_path_d_win = r"C:/Users/" + usermane + r"/" + user_downloads_path+ r"/"

Задаём путь к папке с загрузками для конкретного пользователя


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

if type_os == "Linux":
    downloads_path = os.listdir("/home/" + usermane + "/" + user_downloads_path)
else:
    downloads_path_win = os.listdir(r"C:/Users/" + usermane + r"/" + user_downloads_path)

Ну и также для удобства дальнейшего использования кода зададим путь вида /домашняяпапка/имяпользователя

if type_os == "Linux":
    default_path_u = "/home/" + usermane + "/"
else:
    default_path_u_win = r"C:/Users/" + usermane + r"/"

Проверяем наличие конкретных файлов в папке с загрузками


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

#Проверяем есть ли в папке загрузок аудиофайлы. Если есть, кидаем их в папку Музыка
for music_format in music_folder:
    if type_os == "Linux":
        for name_file in downloads_path:
            if name_file.endswith(music_format):
                result = name_file.split(str(music_format), 1)
                os.rename(default_path_d + result[0] + music_format, default_path_u + music_folder.get(music_format) + result[0] + music_format)
    if type_os == "Windows":
        for name_file in downloads_path_win:
            if name_file.endswith(music_format):
                result = name_file.split(str(music_format), 1)
                os.rename(default_path_d_win + result[0] + music_format, default_path_u_win + "Music" + r"/" + result[0] + music_format)
#Проверяем есть ли в папке загрузок изображения. Если есть, кидаем их в папку Изображения
for pic_format in pic_folder:
    if type_os == "Linux":
        for name_file in downloads_path:
            if name_file.endswith(pic_format):
                result = name_file.split(str(pic_format), 1)
                os.rename(default_path_d + result[0] + pic_format, default_path_u + pic_folder.get(pic_format) + result[0] + pic_format)
    if type_os == "Windows":
        for name_file in downloads_path_win:
            if name_file.endswith(pic_format):
                result = name_file.split(str(pic_format), 1)
                os.rename(default_path_d_win + result[0] + pic_format, default_path_u_win + "Pictures" + r"/" + result[0] + pic_format)
#Проверяем есть ли в папке загрузок документы или архивы. Если есть, кидаем их в папку Документы
for doc_format in doc_folder:
    if type_os == "Linux":
        for name_file in downloads_path:
            if name_file.endswith(doc_format):
                result = name_file.split(str(doc_format), 1)
                os.rename(default_path_d + result[0] + doc_format, default_path_u + doc_folder.get(doc_format) + result[0] + doc_format)
    if type_os == "Windows":
        for name_file in downloads_path_win:
            if name_file.endswith(doc_format):
                result = name_file.split(str(doc_format), 1)
                os.rename(default_path_d_win + result[0] + doc_format, default_path_u_win + "Documents" + r"/" + result[0] + doc_format)

Изначально я планировал решить задачу поиска расширений файлов путём использования регулярных выражений и занимался их формулировкой. Но потом прочитал на одном из сайтов, что если вы желаете решить какую-либо задачу, то только в последнюю очередь нужно пользоваться регулярными выражениями. Python имеет иные более простые и понятные способы сделать то, что от вас требуется. Потому вместо этих выражений расширение файла определяется путём использования строкового метода endswith(). Он берёт ключ из словаря и проверяет заканчивается ли файл на него. Затем при помощи метода split() берётся только имя файла для дальнейшего перемещения при помощи os.rename(). В качестве аргументов последнего используются все ранее созданные переменные.

Спрашиваем у пользователя, что делать с оставшимися файлами


После того, как нужные файлы отсортированы программа должна либо завершиться, либо удалить те файлы, которые не попали под перемещение (например, exe-файлы или deb-пакеты). Решение об этом принимает пользователь, по-умолчанию удаление не происходит.

#Запрос на удаление оставшихся файлов в директории загрузок
delete_user_confirm = input('Удалить из папки загрузок оставшиеся файлы? Напишите да или нет (по-умолчанию: нет) ' or 'нет')
if delete_user_confirm == 'да':
    if type_os == "Linux":
        files_to_remove = os.listdir(default_path_d)
        for remove_files in files_to_remove:
            os.remove(default_path_d + "/" + remove_files)
    if type_os == "Windows":
        files_to_remove = os.listdir(default_path_d_win)
        for remove_files in files_to_remove:
            os.remove(default_path_d_win + "/" + remove_files)
else:
    print('Программа завершила работу. Все файлы размещены.')

Подводя итог


Постарался объяснить то, как работает созданная мной программа как можно понятнее. Но думаю, что желающие разбираться всё равно пересмотрят сам код несколько раз. Perfectionist Organizer представлен в двух версиях — консольной и графической. По ссылке на мой Github можно найти обе, там же приведены инструкции по тому, как скачать и использовать программу. Я прогнал консольную версию на своей основной ОС (Archlinux) и GUI-версию в виртуальной машине на Windows 7. В обоих случаях программа сработала на «УРА». Также хочу прикрепить демонстрацию того, как она работает под Linux. Если эта тема кому-то будет интересна, то в следующей статье расскажу, как я делал GUI-версию и с какими сложностями столкнулся.

Демонстрация работы программы Perfectionist Organizer
image

Планы на будущее


Следующей на очереди программа, которая будет напоминать о важных событиях из таблицы Google Sheets в Telegram'е. Как только закончу её расскажу здесь. Любые свои вопросы и feedback по работе Perfectionist Organizer можете оставлять в комментариях или в личку. Спасибо за внимание!

Комментарии (54)


  1. eumorozov
    21.09.2019 15:13

    Можно побыть немного занудой?


    if type_os == "Linux":
        default_path_d = "/home/" + usermane + "/" + user_downloads_path + "/"
    else:
        default_path_d_win = r"C:/Users/" + usermane + r"/" + user_downloads_path+ r"/"

    Использование модуля pathlib из стандартной библиотеки приводит к гораздо более читаемому и удобному коду. Префикс r в части после else совершенно не нужен. С pathlib код стал бы намного более читабельный, сейчас это какая-то каша, в которой глаза постоянно спотыкаются на бесконечных +.


    Пользовательские каталоги типа Downloads под Linux правильно брать из xdg-user-dirs. В Windows, кстати, пользователь тоже может менять их местоположение.


    1. Aleksashka1990 Автор
      21.09.2019 15:20

      конечно можно и даже нужно :) спасибо за дополнения, учту в сл. раз или может даже перепишу это, чтобы не было кашей. да, в данный момент вообще не учитывается, что пользователь мог перенести Загрузки в другое место.


    1. Lazytech
      22.09.2019 07:37

      Тоже немного побуду занудой: наверное, все-таки не usermane («грива пользователя»), а username («имя пользователя»). :)


      1. maxzhurkin
        22.09.2019 12:55

        Кто-то уже отписал кучу сообщений об ошибке в личку


        1. Aleksashka1990 Автор
          22.09.2019 12:56

          ошибки в основном грамматические, по крайней мере в личке инфа о них


    1. maxzhurkin
      22.09.2019 12:44

      Занудой надо быть последовательно: есть ещё относительно распространённые ОС вроде Free/Net/Open/DraginFlyBSD (пожалуй, примерно в порядке убывания распространённости/популярности), для которых код бы вполне работал, если бы не линуксовиндовый шовинизм автора

      P.S. кажется, я не учёл, что если последовать вашим рекомендациям, он, видимо, и заработает и там. Тем они (рекомендации) ещё ценнее


      1. Aleksashka1990 Автор
        22.09.2019 12:49
        -1

        ну на Windows и Linux работает. а на др. системы я даже не ориентировался. потому что не надо.


        1. eumorozov
          22.09.2019 12:54
          +1

          Оно только у вас работает. Например, я после установки Linux часто меняю каталоги типа ~/Загрузки, потому что много работаю в командной строке, и мне неудобно в командной строке постоянно менять язык и регистр. И все программы корректно это отрабатывают, потому что есть стандарты Free Desktop, которые описывают, где брать местоположения подобных каталогов.


          Для Windows такие стандарты тоже есть, и многие пользователи в Windows тоже переносят подобные каталоги. Например, разбивают диск на два: системный и пользовательский, и переносят каталоги типа Мои Документы на пользовательский раздел (D:\).


          И универсальный инструмент должен использовать эти настройки, тем более, что это совсем несложно.


          1. Aleksashka1990 Автор
            22.09.2019 13:02
            -3

            вы полагаете, что только я после установки системы оставляю папку с загрузками там, где она стоит по-умолчанию? :) а все иные пользователи сразу же начинают её перемещать в другие места? говоря многие вы оперируете достаточно размытыми понятиями. например, число пользователей Office 365 (а следовательно пользователей Windows) достигло 135 млн человек. вы можете назвать какой процент из этих людей переносит папку загрузок после установки системы?


            1. BoogieMan75
              22.09.2019 16:16

              Вы просто делаете не универсальное решение и вам на это пытаются указать, а вы старательно отмазываетесь. Хотите делать что то — старайтесь делать это хорошо.


              1. Aleksashka1990 Автор
                22.09.2019 17:40

                Это не попытка указать на ошибки, а попытка умничать. В этом случае человек пытается выдать свой опыт за то, что делают другие. Чего делать не стоит. Обратите внимание на нормальные указания на ошибки и мою реакцию — увидите разницу. Я с радостью воспринимаю и принимаю критику, но только если это критика, а не выпендреж.


                1. eumorozov
                  23.09.2019 08:51

                  Если я пытаюсь умничать, то как быть с тем, что, например, Ubuntu для установки в каждом языке создает свои каталоги: ~/Рабочий Стол vs ~/Desktop, ~/Загрузки vs ~/Downloads, и т.д. для каждого языка. У каждого пользователя, который при установке выбрал язык отличный от английского, будут другие названия каталогов.


                  Ну и вообще, ваш подход напоминает анекдот про машину для бритья. Что лица у всех разные… до первого использования машины.


                  Удачи в реальном мире с таким подходом!


                  1. Aleksashka1990 Автор
                    23.09.2019 09:05
                    -1

                    Ну так у меня и прописан вариант для русской версии установки. Я не заявлял нигде, что этот код будет работать на всех локализациях Linux. Вы читайте внимательно — в первую очередь я делал это для себя. У меня русская версия Archlinux, Windows в виртуалке. На основании этого и делал. Зачем в таком случае требовать универсальности? Если её изначально не заявлено на данный момент.


                    1. eumorozov
                      23.09.2019 09:10

                      Критику никто не любит, и критиковать правильно никто не умеет.


                      Просто получается, что вы выложили скрипт:


                      1. Неоптимально написаный: трудно читается, не является идиоматичным python-кодом, не использует все возможности стандартной библиотеки, использует неоптимальные структуры данных.
                      2. Не универсальный, подходит для определенных усредненных конфигураций ОС

                      Ну и в чем тогда смысл? Как пример хорошего кода на Python ­— он таким не является. Как инструмент, который может быть полезен другим — тогда надо было сделать более универсальным. Чтобы покритиковали — так мы и критикуем. :)


  1. eumorozov
    21.09.2019 15:20
    +1

    Вот эти словари:


    video_folder = {".3gp" : "Видео/", ".avi" : "Видео/", ".flv" : "Видео/", ".m4v" : "Видео/", ".mkv" : "Видео/", ".mov" : "Видео/", ".mp4" : "Видео/", ".wmv" : "Видео/", ".webm" : "Видео/"}
    music_folder = {".mp3" : "Музыка/", ".aac": "Музыка/", ".flac" : "Музыка/", ".mpc" : "Музыка/", ".wma" : "Музыка/", ".wav" : "Музыка/"}
    pic_folder = {".raw" : "Изображения/", ".jpg" : "Изображения/", ".tiff" : "Изображения/", ".psd" : "Изображения/", ".bmp" : "Изображения/", ".gif" : "Изображения/", ".png" : "Изображения/", ".jp2" : "Изображения/", ".jpeg" : "Изображения/"}
    doc_folder = {".doc" : "Документы/", ".docx" : "Документы/", ".txt" : "Документы/", ".rtf" : "Документы/", ".pdf" : "Документы/", ".fb2" : "Документы/", ".djvu" : "Документы/", ".xls" : "Документы/", ".xlsx" : "Документы/", ".ppt" : "Документы/", ".pptx" : "Документы/", ".mdb" : "Документы/", ".accdb" : "Документы/", ".rar" : "Документы/", ".zip" : "Документы/", ".7z" : "Документы/"}

    отформатированы просто ужасно, невозможно читать. Кроме того, зачем здесь использовать словарь, если у всех ключей одно и то же значение? Налицо неверный выбор структуры данных.


    Ну и дальше работа с этими словарями вызывает… гм… вопросы… Вот это:
    result = name_file.split(str(doc_format), 1)


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


    1. Aleksashka1990 Автор
      21.09.2019 17:56

      Тонкость в том, что совсем не намеренная :) За комментарий спасибо!


    1. Aleksashka1990 Автор
      22.09.2019 09:24

      некому линейкой по рукам бить, я одинок и познаю Python самостоятельно :) потому мне и нужна критика, разбор кода, указание на ошибки. на мой взгляд, это лучше, чем писание «в стол».


      1. eumorozov
        22.09.2019 10:46

        Начинать самостоятельно надо с Python Tutorial. Потом пробежаться по Library Reference, хотя бы бегло, чтобы не изобретать велосипед.


        И когда вы пишете код типа этих адских словарей, которые на 90% состоят из копи-пасты, в тот момент, когда вы 5-й раз писали одно и то же, уже надо остановиться и задать себе вопрос: «А то ли я делаю?»


        Хороший программист почти никогда не копипастит. И не пишет такой boilerplate код. Кстати, вот эти бесконечные конкатенации путей file_name_a + file_name_b в общем из той же оперы.


        1. Aleksashka1990 Автор
          22.09.2019 10:48

          Ну так я пока что и не хороший программист, я только учусь :)


  1. vpiskunov
    21.09.2019 15:30
    +4

    Да простит меня комьюнити за мое мнение, но, еще раз ИМХО, статьи с подобным уровнем подготовки а-ля курсач 3-го курса первого полугодия способствуют общему понижению уровня ресурса.
    Особенно, если учесть использование жутких антипаттернов.


  1. DollaR84
    21.09.2019 16:20

    Я тоже сделаю небольшое замечание по словарям. Постоянное повторение одного и того же куска кода, или значения в словаре, или еще что повторяющееся должно сразу наталкивать на мысль, что здесь что-то не так, и наверняка можно оптимизировать более доступно.
    Например все эти 4 словаря можно преобразовать к одному словарю типа:

    folders = {
                "Видео/": [".3gp", ".avi", ".flv", ".m4v", ".mkv", ".mov", ".mp4", ".wmv", ".webm"],
                "Музыка/": [".mp3", ".aac", ".flac", ".mpc", ".wma", ".wav"],
                "Изображения/": [".raw", ".jpg", ".tiff", ".psd", ".bmp", ".gif", ".png", ".jp2", ".jpeg"],
                "Документы/": [".doc", ".docx", ".txt", ".rtf", ".pdf", ".fb2", ".djvu", ".xls", ".xlsx", ".ppt", ".pptx", ".mdb", ".accdb", ".rar", ".zip", ".7z"]
    }
    

    Тогда потом получится один маленький цикл на 4 итерации. А Наличие расширения в списке можно проверять оператором in.
    Например что-то типа такого:
    ext = #тут вы получаете расширение файла
    for folder, ext_list in folders.items():
        if ext in ext_list:
            #ваш код
    


    1. Aleksashka1990 Автор
      21.09.2019 17:55

      Спасибо за комментарии. Учту в будущем.


    1. Denai
      22.09.2019 00:06

      Здесь точка в каждом из значений не менее лишняя, чем повторение имени папки


      1. DollaR84
        22.09.2019 11:12

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


  1. tsklab
    21.09.2019 18:02

    C:/Users/имяпользователя/Downloads/
    В разных версиях Windows эта папка находится в других местах. И это по-умолчанию, так как её можно переместить или переопределить, опять же в зависимости от версии Windows/


    1. Aleksashka1990 Автор
      21.09.2019 20:09

      В версиях с 7 до 10 папка загрузок всегда находится по одному пути. Проверено уже. А вот возможность переноса это да — я это не учитывал намеренно пока что.


      1. maxzhurkin
        24.09.2019 21:01

        Это только если:

        1. Windows установлена на диске C:
        2. Профиль пользователя находится в C:/Users/имяпользователя/
        3. пользователь никуда не переместил папку загрузок
        4. пользователь не переопределил путь к папке загрузок

        Не многовато ли оговорок для того, чтобы ваши слова соответствовали истине?


  1. Denai
    21.09.2019 20:24

    А с чего вы взяли что папка с загрузками лежит по пути «C:/Users/» + usermane + r"/" + user_downloads_path"?

    ru.wikipedia.org/wiki/%D0%9F%D0%B5%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D0%B0%D1%8F_%D1%81%D1%80%D0%B5%D0%B4%D1%8B


    1. Aleksashka1990 Автор
      21.09.2019 21:47

      Ну вот у вас где папка Загрузки находится?


      1. Denai
        21.09.2019 21:48
        +1

        D:/downloads/


        1. DollaR84
          21.09.2019 22:24
          +1

          Кстати, у меня точно такой же адрес :)


        1. Aleksashka1990 Автор
          21.09.2019 22:44

          Но это явно не стандартный путь. Вариант, при котором папка перемещена пользователем я пока что не рассматривал даже.


          1. andreymal
            21.09.2019 22:48

            А зря. Плюс одна ошибка в статье. У меня вот папки загрузки тоже расположены не по стандартным путям ни в винде, ни в линуксе.


            И домашняя папка пользователя целиком тоже может быть перемещена как минимум в линуксе.


            1. Aleksashka1990 Автор
              21.09.2019 22:49

              Все придёт со временем


  1. cy-ernado
    21.09.2019 20:27
    +1

    Очень напомнило мою первую программу на питоне восьмилетней давности, правда я там всё же выбрал регекспы :)


  1. resetme
    22.09.2019 00:16

    А если у меня MacOS?


    1. Aleksashka1990 Автор
      22.09.2019 08:13

      Об этом в тексте статьи я написал уже.


  1. Denai
    22.09.2019 00:18

    А что произойдёт, если в папку для перемещения прав на запись не будет или самой папки не будет или она совпадёт с исходной или файл будет занят другим процессом на момент перемещения, но не будет занят на момент завершения (при включённом удалении)? А с симлинками и вложенными папками что будет? Если места не хватит для переноса файлов, они все в конце удалятся?


  1. BoogieMan75
    22.09.2019 09:19

    А почему типы файлов не хранить в отдельном конфиге?


    1. Oxyd
      22.09.2019 10:53

      И собственно пути до целевых директорий.


  1. felix21
    22.09.2019 09:22

    Надо сделать примерно то же, но с целым диском (500 Гб, ntfs). На нем после восстановления данных образовалось около четырехсот папок до тысячи файлов в каждой. Надо отсортировать их по расширениям и положить в соответствующие папки. Система основана на Archlinux, если что.
    Есть ли несложный способ для выполнения этой задачи?


    1. svk28
      22.09.2019 12:31

      Примерно так:
      shell>: export OUTDIR=~/tmp/mp3; mkdir $OUTDIR; find /mnt/disk/ -type f -name "*.mp3" -print -exec cp {} $OUTDIR \;

      Данная команда найдет все mp3-файлы в каталоге /mnt/disk (куда примонтирован диск) и скопирует их в созданный каталог tmp/mp3 в домашнем каталоге пользователя.
      Если я правильно понял задачу.
      Если нужно переместить, то «cp» меняется на «mv», но сперва лучше попробовать с копированием =)

      Это решение в лоб, но по хорошему надо сразу автоматом анализировать типы файлов, создавать соответственно каталоги и копировать туда.


      1. felix21
        23.09.2019 14:40

        Спасибо, Вы правильно поняли задачу. Только желательно сразу перемещать файлы в соответствующие папки на том же диске, ибо под линукс отрезано не так много места на диске.
        Если бы ещё и папки автоматом создавались… ))) Но это не принципиально.


  1. bogolt
    22.09.2019 10:14

    лучше объединять пути через

    os.path.join(root, dir)

    Спрашивать у пользователя в тексте ввод директории не очень для него удобно. Легко допустить ошибку при вводе. Навреное лучше подключиться к одной из гуи библиотек и показать нормальное окно выбора директории. что-то типа PyWx или PyQt подойдет, хотя конечно подключать их для одного окна это жуткий оверкилл ( хотя кого я обманываю сейчас весь софт так пишется ).


    1. Aleksashka1990 Автор
      22.09.2019 10:20

      спасибо за подсказку


    1. eumorozov
      22.09.2019 10:33

      Нет уже смысла использовать os.path.joinpathlib во много раз удобнее.


      1. devpony
        22.09.2019 14:47
        -1

        Код использующий pathlib очень плохо читается и слишком неявный в отличии от os.path.join.


        1. eumorozov
          22.09.2019 14:53

          А можно пример, где он плохо читается? Я мало работаю с путями, и там, где использюу, мне кажется, что выглядит вполне читаемо.


          1. devpony
            23.09.2019 13:24

            В одном открытом проекте встречал:


            path = long_var_name_a / long_var_name_b /
                long_var_name_c / long_var_name_d / long_var_name_e

            Вместо:


            path = os.path.join(
                long_var_name_a,
                long_var_name_b,
                long_var_name_c,
                long_var_name_d,
                long_var_name_e,
            )

            Форматирование это только одна проблема. Если не держать в голове, что в переменных пути, придётся отматывать контекст назад, пытаясь понять, что же здесь на что делится. С join такой проблемы нет, он задаёт контекст сразу же.


    1. kAIST
      22.09.2019 22:33

      Да можно же использовать tkinter, который на windows к тому же идет в комплекте с питоном. Системный диалог выбор директории, реализуется в одну строчку (кроме импорта конечно же)


      1. Aleksashka1990 Автор
        22.09.2019 22:40

        У меня Archlinux, потому я ориентировался в первую очередь на Linux-based дистрибутивы.


        1. andreymal
          22.09.2019 22:44

          У арча tkinter тоже никто не отбирал.


  1. oldmelnik99
    22.09.2019 22:21
    -1

    Wow. Гениально, лайк!


  1. puyol_dev2
    22.09.2019 23:25
    -1

    Одной строчкой на питоне. Где-то уже это слышал…