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

в 15:27, , рубрики: python

Возможно, у вас возникло желание, например, при просмотре фото в своей папке перемешать их, смотреть их в случайном порядке. Т.к. (как минимум на 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()

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

Автор: Леонид Якубович

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js