![]() |
Neste artigo vou mostrar como deletar arquivos duplicados em uma pasta usando a linguagem C#. |
Para melhorar um pouco a interface com o usuário vamo usar o controle TreeView para exibir os arquivos duplicados com uma checkbox.
Para
consultar os arquivos duplicados vamos verificar o hash code do
arquivo, e assim, se dois arquivos possuirem o mesmo hash code temos 99% de
certeza de que eles são o mesmo arquivo.
Recursos Usados
Criando o projeto Windows Forms
Abra o VS 2017 Community e crie um novo projeto (File-> New Project) usando a linguagem C# e o template Windows Forms App (.NET Framework).
Informe um nome a seu gosto. Eu vou usar o nome CShp_Arquivos;
No formulário Form1 do projeto inclua os seguintes controles a partir da ToolBox:
Disponha os controles conforme o leiaute da figura abaixo:
![]() |
Inclua uma referência no projeto ao namespace : Microsoft.VisualBasic
A seguir inclua no formulário os seguintes namespaces:
using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Windows.Forms;
using Microsoft.VisualBasic.FileIO;
No início do formulário vamos declarar as variáveis objeto para criar uma
instância do serviço MD5 e definir uma variável para definir o estado de
excluir um arquivo:
private MD5 Md5 =
MD5.Create();
private bool Deleting = false;
No evento Click do botão - btnDiretorio - para selecionar o diretório inclua o código abra a janela de diálogo FolderBrowserDialog :
No botão para Procurar inclua no evento Click o código abaixo que procurar por arquivo duplicados
private void btnProcurar_Click(object sender, EventArgs e)
{
tvArquivos.Visible = false;
tvArquivos.Nodes.Clear();
lblNumeroArquivosDuplicados.Text = "";
Refresh();
try
{
// Obtem uma lista de arquivos e seus valores de hash
var get_info =
from string _nomeArquivo in Directory.GetFiles(txtDiretorio.Text)
select new
{
Name = _nomeArquivo,
Hash = BytesToString(GetHash(_nomeArquivo))
};
// Agrupa os arquivos por valor de hash
var group_infos =
from info in get_info
group info by info.Hash into g
where g.Count() > 1
//orderby g.Key
select g;
// percore os arquivos
int num_groups = 0;
int num_arquivos = 0;
foreach (var g in group_infos)
{
num_groups++;
TreeNode hash_node = tvArquivos.Nodes.Add(g.Key.ToString());
foreach (var info in g)
{
num_arquivos++;
TreeNode arquivo_node = new TreeNode(info.Name);
arquivo_node.Tag = new FileInfo(info.Name);
hash_node.Nodes.Add(arquivo_node);
}
}
// Exibe o numero de arquivos duplicados
lblNumeroArquivosDuplicados.Text = (num_arquivos - num_groups).ToString() +
" arquivos duplicados";
// Expande os nodes.
tvArquivos.ExpandAll();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
// Cai para o topo
if (tvArquivos.Nodes.Count > 0)
tvArquivos.Nodes[0].EnsureVisible();
tvArquivos.Visible = true;
}
}
|
No código usamos uma consulta LINQ que faz um loop nos arquivos retornados pelo método Directory.GetFiles, e retorna os nomes dos arquivos em um diretório.
Para cada arquivo, a consulta seleciona o nome do arquivo e o código hash MD5 do arquivo.
A seguir usamos outra consulta LINQ para agrupar os resultados da primeira consulta por código hash. Selecionando apenas grupos em que o número de arquivos no grupo (isto é, o mesmo código hash) é maior que um. O resultado é uma consulta que retorna grupos contendo pelo menos dois arquivos com os mesmos códigos de hash.
Tendo construído a consulta de agrupamento, o programa percorre os grupos. Para cada grupo, o programa adiciona um nó de nível superior ao controle TreeView exibindo o código de hash. Em seguida, ele passa pelo conteúdo do grupo.
Cada item do grupo contém o nome e o código de hash de um arquivo. O código cria um nó filho para o arquivo, definindo seu texto como igual ao nome do arquivo. Ele também define a propriedade Tag do nó filho como um objeto FileInfo que representa o arquivo. Mais tarde, ele pode usar esse objeto para exibir ou excluir o arquivo.
Conforme processa os grupos, o código mantém o controle do número de
arquivos duplicados e do número de grupos. Depois, ele informa o número de
arquivos duplicados.
Continuando, o código expande todos os nós do controle TreeView para que
você possa ver todos os arquivos duplicados. Ele também rola para o topo do
controle TreeView.
A seguir temos os métodos BytesToString() e GetHash() usados para realizar as tarefas de retornar um hash como uma string e calcular o hash do arquivo:
No evento Click do botão Selecionar Arquivos duplicados temos o código que marca os checkbox dos arquivos duplicados:
Finamente temos o evento Click do botão - Deletar Arquivos - que inclui o arquivo na lixeira e depois deleta o arquivo :
private void DeletarDuplicados_Click(object sender, EventArgs e)
{
Deleting = true;
tvArquivos.Visible = false;
lblNumeroArquivosDuplicados.Text = "";
Refresh();
try
{
// Faz uma lista de nodes para deletar
List<TreeNode> nodes_para_deletar = new List<TreeNode>();
foreach (TreeNode hash_node in tvArquivos.Nodes)
{
foreach (TreeNode arquivo_node in hash_node.Nodes)
{
// Verifica se o arquivo do node esta marcado(checked.)
if (arquivo_node.Checked) nodes_para_deletar.Add(arquivo_node);
}
}
// Deleta os nodes selecionados e seus arquivos
foreach (TreeNode arquivo_node in nodes_para_deletar)
{
// Obtem o FileInfo da propriedadae Tag
FileInfo file_info = arquivo_node.Tag as FileInfo;
// Move o arquivo para a lixeira
DeletarArquivo(file_info.FullName);
// Remove o arquivo do TreeView.
arquivo_node.Remove();
}
// Faz uma lista do tamanho dos nodes com os filhos restantes
nodes_para_deletar = new List<TreeNode>();
foreach (TreeNode hash_node in tvArquivos.Nodes)
{
if (hash_node.Nodes.Count == 0) nodes_para_deletar.Add(hash_node);
}
// Deleta o tamanho dos nodes com os filhos
foreach (TreeNode hash_node in nodes_para_deletar)
{
hash_node.Remove();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
// Rola para o topo
if (tvArquivos.Nodes.Count > 0)
tvArquivos.Nodes[0].EnsureVisible();
tvArquivos.Visible = true;
Deleting = false;
}
}
|
A seguir temos o método DeletarArquivo() e suas sobrecargas :
Executando o projeto e iremos obter:
![]() |
Pegue
o projeto completo aqui :
CShp_ArquivosDuplicados.zip
"Disse-lhe Jesus:
Eu sou o caminho, e a verdade e a vida; ninguém vem ao Pai, senão por mim."
João 14:6
Veja os
Destaques e novidades do SUPER DVD Visual Basic (sempre atualizado) : clique
e confira !
Quer migrar para o VB .NET ?
Quer aprender C# ??
Quer aprender os conceitos da Programação Orientada a objetos ? Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ? Quer aprender a criar aplicações Web Dinâmicas usando a ASP .NET MVC 5 ? |
Gostou ?
Compartilhe no Facebook
Compartilhe no Twitter
Referências:
Super DVD Vídeo Aulas - Vídeo Aula sobre VB .NET, ASP .NET e C#
Visual Studio - Dica de produtividade - Quick Launch - Macoratti.net
Visual Studio - Dica de produtividade - Nuget - Macoratti.net
VB .NET - O Calculando o CheckSum para um arquivo - Macoratti
VB.NET - Criar, Ler, Escrever, Copiar e Deletar arquivos ... - Macoratti
C# - Lendo e escrevendo em arquivos textos e binários - Macoratti
.NET - Trabalhando com propriedades e atributos de arquivos e ...