Organizador de Arquivos em Python + tkinter
Publicado por Pedro Fernandes (última atualização em 30/04/2023)
[ Hits: 2.195 ]
Homepage: https://github.com/PedroF37
Download Organizador-de-Arquivos.7z
Projeto de automação em Python (Organizador de Arquivos)
Dada uma pasta com vários arquivos de várias extensões, aplicativo permite guardar arquivos em pastas nomeadas com a extensão; arquivos .pdf na pasta pdf, arquivos .txt na pasta txt etc.
Aplicativo permite também arquivar e comprimir arquivos, usando formato tar.xz (txz) e deletar arquivos. Projeto trabalha apenas com arquivos, não com pastas. Projeto também não faz recursão em pasta, ou seja, não procura dentro de subpastas.
Configuração é simples: arquivo extensions.py, tem a lista das extensões de arquivos reconhecidos. Basta adicionar (ou deletar) extensões. Feito.
Fonte usada: Roboto
Projeto feito para praticar (não que seja algo útil kkk)
Original:
https://github.com/PedroF37/Organizador-de-Arquivos
Arquivo: frontend.py
# -------------------------------------------------------------------------- #
# IMPORTAÇÕES
# tkinter
from tkinter import Tk, Frame, Label, Button, PhotoImage
from tkinter.messagebox import showinfo, showwarning
from tkinter.filedialog import askdirectory
from tkinter.ttk import Style, Combobox
# matplotlib
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import matplotlib.pyplot as plt
# pathlib
from pathlib import Path
# os
from os import chdir, getcwd
# sys
from sys import exit
# views
from views import list_directory, organize_files
from views import compress_files, compress_all_files
from views import delete_files, delete_all_files
# -------------------------------------------------------------------------- #
# CONSTANTES
# Cores
COLOR1 = '#464646' # Fundo
COLOR2 = '#ffffff' # Letra
COLOR3 = '#676767' # Linha de separação
# Home do usuário
home = Path.home()
# -------------------------------------------------------------------------- #
# FUNÇÕES
def choose_folder():
"""Cuida da escolha da pasta alvo."""
try:
target_folder = askdirectory(initialdir=home)
# Para não dar um erro feioso se fechar a janela principal
except Exception as err:
exit()
else:
'''
dicionario tem como chave a extensão e como valor o número
de arquivos com essa extensão. Em ext_list, uso do facto de que
por padrão o dicionário retorna a chave, logo não precisa colocar
filedict.keys(). number_list e legend_list são para o gráfico pie.
ext_list é para os combobox. legend_list é algo como: .pdf : 35
O "if target_folder:", trata do caso de apertar botão de cancelar.
Quando isso acontece, dá erro de "TypeError" e mesmo com except não
sei como tratar de forma que não apareca outra mensagem feiosa
na tela. Logo, temos "if target_folder:" ...
'''
if target_folder:
size, filedict = list_directory(target_folder)
number_list = [number for number in filedict.values()]
ext_list = [ext for ext in filedict]
legend_list = [
f'{ext} : {number}'
for ext, number in filedict.items()
]
# Aqui, é para o caso de não ter arquivos, não mostrar
# a legenda e o título sem o gráfico (que fica feioso kk)
if size > 0:
pie_graph(size, number_list, legend_list)
else:
showinfo('', 'Pasta selecionada está vazia')
return
# 'insert('.*')', para dar opção de compactar/deletar
# todos os arquivos
ext_list.insert(0, '.*')
delete_combobox['values'] = ext_list
extension_combobox['values'] = ext_list
organize_button['state'] = 'active'
compact_button['state'] = 'active'
delete_button['state'] = 'active'
organize_button['command'] = lambda: organize(target_folder)
compact_button['command'] = lambda: compress(target_folder)
delete_button['command'] = lambda: choose_delete(target_folder)
else:
exit()
def organize(target_folder):
"""Cuida de chamar função que organiza arquivos."""
organize_files(target_folder)
showinfo('', 'Arquivos organizados com sucesso')
reset_app()
def compress(target_folder):
"""Cuida de chamar função que compacta arquivos."""
if not extension_combobox.get():
showwarning('', 'Tem que selecionar uma extensão')
return
# TODOS os arquivos
elif extension_combobox.get() == '.*':
compress_all_files(target_folder)
else:
# Somente para a extensão escolhida
compress_files(target_folder, extension_combobox.get())
showinfo('', 'Arquivos comprimidos com sucesso')
reset_app()
def choose_delete(target_folder):
"""Cuida de chamar função que deleta arquivos."""
if not delete_combobox.get():
showwarning('', 'Tem que selecionar uma extensão')
return
# Age sob TODOS os arquivos
elif delete_combobox.get() == '.*':
delete_all_files(target_folder)
else:
# Somente para a extensão escolhida
delete_files(target_folder, delete_combobox.get())
showinfo('', 'Arquivos deletados com sucesso')
reset_app()
def pie_graph(size, number_list, legend_list):
"""
Cuida de mostrar gráfico pizza
com as extensões e número por cada
extensão no diretório.
"""
graph = plt.Figure(figsize=(5, 3), dpi=90)
ax = graph.add_subplot(111)
ax.pie(
number_list,
wedgeprops=dict(width=0.3),
shadow=True, startangle=90
)
# Deu um trabalhão para descobrir
# como fazer isto!! kkk
ax.set_title(
f'Tamanho Total: {size} MB',
color='w', weight='bold',
fontsize=10
)
ax.legend(
legend_list, loc="lower center",
bbox_to_anchor=(1.30, 0.50),
title='Quantidade'
)
# Coloca o fundo do gráfico igual ao fundo do app
graph.patch.set_facecolor(COLOR1)
canvas = FigureCanvasTkAgg(graph, output_frame)
canvas.get_tk_widget().place(x=-60, y=0)
def reset_app():
"""Cuida de resetar todo o app."""
chdir(home)
organize_button['state'] = 'disabled'
compact_button['state'] = 'disabled'
delete_button['state'] = 'disabled'
delete_combobox['values'] = ''
delete_combobox.set('')
extension_combobox['values'] = ''
extension_combobox.set('')
# -------------------------------------------------------------------------- #
# JANELA
window = Tk()
window.title('')
window.geometry('800x400')
window.resizable(width=False, height=False)
window.configure(background=COLOR1)
style = Style(window)
style.theme_use('clam')
# -------------------------------------------------------------------------- #
# FRAMES
title_frame = Frame(window, width=800, height=50, bg=COLOR1)
title_frame.grid(row=0, column=0, sticky='nw')
operation_frame = Frame(window, width=400, height=350, bg=COLOR1)
operation_frame.grid(row=1, column=0, sticky='nw')
output_frame = Frame(window, width=400, height=350, bg=COLOR1)
output_frame.place(x=400, y=50)
# -------------------------------------------------------------------------- #
# CONFIGURANDO TITLE_FRAME
logo = PhotoImage(file='icones/logo.png')
title_label = Label(
title_frame, width=800, image=logo,
text=' Organizador de Arquivos',
compound='left', font=('Roboto 15 bold'),
anchor='nw', bg=COLOR1, fg=COLOR2
)
title_label.place(x=10, y=10)
separator_label = Label(
title_frame, width=800,
text='', font=('Roboto 1'),
bg=COLOR3
)
separator_label.place(x=0, y=48)
# -------------------------------------------------------------------------- #
# CONFIGURANDO OPERATION_FRAME
# Escolher pasta
folder_choose_label = Label(
operation_frame, width=70,
text='Selecione a pasta',
font=('Roboto 10 bold'), anchor='nw',
fg=COLOR2, bg=COLOR1
)
folder_choose_label.place(x=15, y=15)
folder_img = PhotoImage(file='icones/folder.png')
folder_button = Button(
operation_frame, width=100, image=folder_img, text='PASTA',
compound='left', font=('Roboto 8 bold'), anchor='nw',
relief='ridge', overrelief='sunken', bd=0, borderwidth=0,
bg=COLOR1, fg=COLOR2, activebackground=COLOR1,
activeforeground=COLOR2, command=choose_folder
)
folder_button.place(x=10, y=40)
# Opção para organizar arquivos
organize_label = Label(
operation_frame, width=70, text='Organizar Arquivos',
font=('Roboto 10 bold'), anchor='nw',
fg=COLOR2, bg=COLOR1
)
organize_label.place(x=160, y=15)
organize_img = PhotoImage(file='icones/organize.png')
organize_button = Button(
operation_frame, width=100, image=organize_img, text='ORGANIZAR',
compound='left', font=('Roboto 8 bold'), anchor='nw',
relief='ridge', overrelief='sunken', bd=0, borderwidth=0,
bg=COLOR1, fg=COLOR2, activebackground=COLOR1,
activeforeground=COLOR2
)
organize_button['state'] = 'disabled'
organize_button.place(x=160, y=40)
# Opção para comprimirr arquivos
compact_label = Label(
operation_frame, width=70, text='Comprimir Arquivos',
font=('Roboto 10 bold'), anchor='nw',
fg=COLOR2, bg=COLOR1
)
compact_label.place(x=10, y=80)
extension_combobox = Combobox(operation_frame, width=12)
extension_combobox['state'] = 'readonly'
extension_combobox.place(x=10, y=105)
compact_img = PhotoImage(file='icones/compact.png')
compact_button = Button(
operation_frame, width=100, image=compact_img, text='COMPRIMIR',
compound='left', font=('Roboto 8 bold'), anchor='nw',
relief='ridge', overrelief='sunken', bd=0, borderwidth=0,
bg=COLOR1, fg=COLOR2, activebackground=COLOR1,
activeforeground=COLOR2
)
compact_button['state'] = 'disabled'
compact_button.place(x=160, y=105)
# Opção para deletar arquivos
delete_label = Label(
operation_frame, width=70, text='Deletar Arquivos',
font=('Roboto 10 bold'), anchor='nw',
fg=COLOR2, bg=COLOR1
)
delete_label.place(x=10, y=135)
delete_combobox = Combobox(operation_frame, width=12)
delete_combobox['state'] = 'readonly'
delete_combobox.place(x=10, y=160)
delete_img = PhotoImage(file='icones/delete.png')
delete_button = Button(
operation_frame, width=100, image=delete_img, text='DELETAR',
compound='left', font=('Roboto 8 bold'), anchor='nw',
relief='ridge', overrelief='sunken', bd=0, borderwidth=0,
bg=COLOR1, fg=COLOR2, activebackground=COLOR1,
activeforeground=COLOR2
)
delete_button['state'] = 'disabled'
delete_button.place(x=160, y=160)
# -------------------------------------------------------------------------- #
# LOOP
window.mainloop()
# -------------------------------------------------------------------------- #
#####################################################################################
Arquivo: views.py
# -------------------------------------------------------------------------- #
# IMPORTAÇÕES
# os
from os import mkdir, chdir, remove, stat
from os.path import splitext
# shutil
from shutil import move
# glob
from glob import glob
# tarfile
import tarfile
# extensions
from extensions import extension_list
# -------------------------------------------------------------------------- #
# FUNÇÕES
def list_directory(directory):
"""Cuida de fazer a contagem das extensões."""
chdir(directory)
# Este é para a legenda do gráfico de pizza
extension_dict = dict()
# Este vai somando o tamanho de cada arquivo e depois
# 'total_size' pega o tamanho total, para usar
# no título do gráfico de pizza.
extension_size = dict()
for item in glob('*.*'):
filename, ext = splitext(item)
if ext in extension_list:
extension_dict.setdefault(ext, 0)
extension_size.setdefault(ext, 0)
extension_dict[ext] += 1
extension_size[ext] += stat(item).st_size / (1024 * 1024)
total_size = sum([round(value, 2) for value in extension_size.values()])
return total_size, extension_dict
def organize_files(directory):
"""Cuida de organizar os arquivos em pastas."""
chdir(directory)
for item in glob('*.*'):
filename, ext = splitext(item)
if ext in extension_list:
new_directory = ext[1:]
try:
mkdir(new_directory)
except FileExistsError:
pass
finally:
move(item, new_directory)
def compress_files(directory, extension):
"""Cuida de compactar arquivos baseado na extensão."""
chdir(directory)
archive = 'archive.txz'
with tarfile.open(archive, 'w:xz') as tar:
[tar.add(item) for item in glob(f'*{extension}')]
def compress_all_files(directory):
"""Cuida de compactar TODOS os arquivos."""
chdir(directory)
archive = 'archive.txz'
with tarfile.open(archive, 'w:xz') as tar:
for item in glob('*.*'):
filename, ext = splitext(item)
if ext in extension_list:
tar.add(item)
def delete_files(directory, extension):
"""Cuida de deletar arquivos baseado na extensão."""
chdir(directory)
[remove(item) for item in glob(f'*{extension}')]
def delete_all_files(directory):
"""Cuida de deletar TODOS os arquivos."""
chdir(directory)
for item in glob('*.*'):
filename, ext = splitext(item)
if ext in extension_list:
remove(item)
# -------------------------------------------------------------------------- #
###################################################################################
Arquivo: extensions.py
'''
Lista de extensões de arquivos permitidos. Coloque mais extensões
a gosto e preferência, especialmente formatos office, que não uso office
e não conheco as extensões. '.*', significa todas as extensões e não
pode ser removida da lista, pois é para a opção de compactar/deletar
todos os arquivos.
'''
extension_list = [
'.txt', '.pdf', '.docx', '.xlsx', '.bak', '.conf', '.config',
'.sh', '.bash', '.py', '.c', '.html', '.css', '.list', '.log',
'.avi', '.mkv', '.mp3', '.mp4', '.x264', '.x265', '.epub', '.mobi',
'.azw3', '.png', '.jpg'
]
Script para fazer o Scroll Lock funcionar no Linux
Modo Simples de Baixar e Usar o bash-completion
Monitorando o Preço do Bitcoin ou sua Cripto Favorita em Tempo Real com um Widget Flutuante
Adicionar botão "mostrar área de trabalho" no Zorin OS
Como montar um servidor de backup no linux
Trazendo de volta o Serviços em Segundo Plano no Plasma6









