Pull to refresh

Перемешивание файлов в папке

Возможно, у вас возникло желание, например, при просмотре фото в своей папке перемешать их, смотреть их в случайном порядке. Т.к. (как минимум на Windows 7) возможно только отсортировать файлы по их имени, размеру и т.д., я решил создать программу, для перемешивания нужных файлов.

Принцип ее работы:

Переименовывание всех файлов в папке (кроме других папок, находящихся внутри), выбранной пользователем: в случайном порядке присваиваются имена 0, 1, 2… Таким образом, при сортировки файлов по имени получается случайная последовательность.

Разберем же код этой программы (он, кстати, написан на Python 3+). Если есть желание скачать эту программу в расширении .pyw и .exe, то вот ссылки
pyw файл
exe файл.

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

import os
import random
from tkinter import *
from tkinter.filedialog import *

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

root = Tk()
root.geometry('200x100')
root.title('Mix')
pth = Label(root, text = '"Выбранный путь"', font = ('Times', 15))
bt = Button(root, text = "Выбрать папку", command = FoldChoose)
bt2 = Button(root, text = "Перемешать", command = Shuf)

pth.pack()
bt.pack()
bt2.pack()
root.mainloop()

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

В первой кнопке присутствует функция. Разберем ее:

def FoldChoose():
    try:
        global vvd
        #запрашивание папки
        vvd = askdirectory()
        pth.config(text = vvd)
        global msv
        msv = os.listdir(path = vvd)
        #перемешивание массива
        random.shuffle(msv)
        if len(vvd) > 20:
            s = (len(vvd) - 20) * 10 + 200
            root.geometry(str(s) + 'x100')
    except Exception:
        return

При нажатии на кнопку будет всплывать диалоговое окно для выбора нужной директории. Этот путь отобразится в label'е. После, благодаря прекрасной функции os.listdir(), все содержимое папки заносится в массив msv, после перемешивается. Если путь перестает вмещаться в окно, это окно расширяется до нужных размеров. Если произойдет исключение (например, пользователь ничего не выберет и просто закроет диалоговое окно), то произойдет выход из функции и ничего не поменяется.

Функция второй кнопки, перемешивание:

def Shuf():
    #если вдруг будет папка с названием вспомогательной папки
    if (os.path.exists(vvd + "/DelThisFold") == True) and (vvd != ''):
        pth.config(text = 'Пожалуйста, удалите\nпапку DelThisFold')
        return
    
    try:
        #создание вспомогательной папки для избежания конфликтов имен
        os.mkdir(vvd + "/DelThisFold")
    except Exception:
        return
    
    #переименовывание файлов, перемещая их во вспомогательную папку
    for i in range(len(msv)):
        frmt = msv[i].split('.')
        g = len(frmt) - 1
        if g != 0:
            os.rename(vvd + "/" + str(msv[i]),
                      vvd + "/DelThisFold/" + str(i) + '.' + frmt[g])
        elif os.path.exists(vvd + "/" + str(msv[i])) == True:
            pass
        else:
            os.rename(vvd + "/" + str(msv[i]),
                      vvd + "/DelThisFold/" + str(i))
    
    #новый массив файлов с измененными именами
    lst = os.listdir(path= vvd + "/DelThisFold")
    
    #перемещение файлов в их начальную папку
    for j in range(len(lst)):
        os.rename(vvd + "/DelThisFold/" + str(lst[j]),
                  vvd + "/" + str(lst[j]))
    
    #удаление вспомогательной папки
    os.rmdir(vvd + "/DelThisFold")

    #окно выхода
    root.destroy()
    qt = Tk()
    qt.geometry('200x120')
    qt.title('Готово!')
    qt_txt = Label(qt, text = "Перемешивание\nзавершено",font = ('Times', 15))
    knpk = Button(qt, text = 'OK', command = qt.destroy, width = 15)
    
    qt_txt.pack()
    knpk.pack()

Да, она огромна. Что ж, мы имеем перемешанный массив файлов папки. Чтобы избежать конфликта имен, нам нужно создать временную вспомогательную папку DelThisFold. В нее мы будем перекидывать только что переименованные файлы. Если вдруг папка с таким именем уже существует, то программа попросит пользователя удалить эту папку.

    #если вдруг будет папка с названием вспомогательной папки
    if (os.path.exists(vvd + "/DelThisFold") == True) and (vvd != ''):
        pth.config(text = 'Пожалуйста, удалите\nпапку DelThisFold')
        return
    
    try:
        #создание вспомогательной папки для избежания конфликтов имен
        os.mkdir(vvd + "/DelThisFold")
    except Exception:
        return

Теперь нам нужно каким-то образом сохранить расширения файлов при перемещении, а также игнорировать папки. Для этого создается переменная frmt, в которую записывается формат текущего файла. Если у файла нет расширения, то мы проверяем, папка ли это. Если это не папка, то это просто файл без расширения, который, как и файлы с расширениями, переносится во вспомогательную папку и переименовывается. Имя берется из переменной цикла.

    #переименовывание файлов, перемещая их во вспомогательную папку
    for i in range(len(msv)):
        frmt = msv[i].split('.')
        g = len(frmt) - 1
        if g != 0:
            os.rename(vvd + "/" + str(msv[i]),
                      vvd + "/DelThisFold/" + str(i) + '.' + frmt[g])
        elif os.path.exists(vvd + "/" + str(msv[i])) == True:
            pass
        else:
            os.rename(vvd + "/" + str(msv[i]),
                      vvd + "/DelThisFold/" + str(i))

После переноса и переименовывания всех файлов, эти файлы вновь заносятся в новый массив. Далее они перемещаются в изначальную папку, а после вспомогательная папка удаляется.

    #новый массив файлов с измененными именами
    lst = os.listdir(path= vvd + "/DelThisFold")
    
    #перемещение файлов в их начальную папку
    for j in range(len(lst)):
        os.rename(vvd + "/DelThisFold/" + str(lst[j]),
                  vvd + "/" + str(lst[j]))
    
    #удаление вспомогательной папки
    os.rmdir(vvd + "/DelThisFold")

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

    #окно выхода
    root.destroy()
    qt = Tk()
    qt.geometry('200x120')
    qt.title('Готово!')
    qt_txt = Label(qt, text = "Перемешивание\nзавершено",font = ('Times', 15))
    knpk = Button(qt, text = 'OK', command = qt.destroy, width = 15)
    
    qt_txt.pack()
    knpk.pack()

Скорее всего, этот код можно было написать лучше. Но я все же надеюсь, что информация, данная мною выше, и сама программа были хоть кому-то полезны.
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.
Change theme settings