Organizador de Arquivos em Python + tkinter
Publicado por Pedro Fernandes (última atualização em 30/04/2023)
[ Hits: 2.126 ]
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'
]
Conversor de Temperaturas Kelvin Celsius e Fahrenheit
Jogo da Velha com IA (Inteligencia Artificial)
Fazendo processos rodarem em background
Como extrair chaves TOTP 2FA a partir de QRCODE (Google Authenticator)
Linux em 2025: Segurança prática para o usuário
Desktop Linux em alta: novos apps, distros e privacidade marcam o sábado
IA chega ao desktop e impulsiona produtividade no mundo Linux
Novos apps de produtividade, avanços em IA e distros em ebulição agitam o universo Linux
Como instalar o repositório do DBeaver no Ubuntu
Como instalar o Plex Media Server no Ubuntu
Digitando underscore com "shift" + "barra de espaços"
Como ativar a lixeira e recuperar aquivos deletados em um servidor Linux
Como mudar o nome de dispositivos Bluetooth via linha de comando
O programa assinador digital (0)
dpkg: erro: gatilho de arquivo duplicado chamado pelo arquivo de nome (6)
Instalação não está resolvendo as dependencias (2)
Captação de áudio no zorin linux começa a diminuir com o tempo (5)









