Skip to content

Instantly share code, notes, and snippets.

@viniciusgonmelo
Last active June 13, 2023 22:54
Show Gist options
  • Save viniciusgonmelo/5a015306e7c4b605082a666dea7e1491 to your computer and use it in GitHub Desktop.
Save viniciusgonmelo/5a015306e7c4b605082a666dea7e1491 to your computer and use it in GitHub Desktop.
Remove arquivos duplicados em um ou mais diretórios
#!/usr/bin/env perl
# Script: rm-duplicates
# Descrição: Remove arquivos duplicados em um ou mais diretórios
# se nenhum diretório for fornecido, o diretório atual será utilizado.
# Exemplo de uso: ./rm-duplicates --dir=/caminho/do/diretório --dir=/caminho/de/outro/diretório
use 5.010;
use strict;
use warnings;
use Digest::MD5;
use File::Find;
use File::Basename;
use Cwd qw(abs_path);
use Getopt::Long;
use Log::Log4perl qw(:easy);
# Configuração de log
# Diretório de log: /var/log/$USER; deve existir e o usuário deve ter permissões
# para escrita; sudo sh -c 'mkdir /var/log/$USER && chown $USER /var/log/$USER'
my $script_name = basename $0;
my $user_name = my $username = $ENV{LOGNAME} || $ENV{USER} || getpwuid($<);
my $log_file = '/var/log/' . $user_name . '/' . $script_name . '.log';
my $conf = <<"EOF";
log4perl.rootLogger = DEBUG, file, screen
log4perl.appender.screen = Log::Log4perl::Appender::Screen
log4perl.appender.screen.stderr = 0
log4perl.appender.screen.layout = PatternLayout
log4perl.appender.screen.layout.ConversionPattern = %d %m%n
log4perl.appender.file = Log::Log4perl::Appender::File
log4perl.appender.file.filename = $log_file
log4perl.appender.file.mode = append
log4perl.appender.file.layout = PatternLayout
log4perl.appender.file.layout.ConversionPattern = %d %m%n
EOF
Log::Log4perl::init( \$conf );
sub main {
my $help;
my @dirs;
GetOptions(
"help" => \$help,
);
if ($help) {
print_usage();
exit;
}
# Processa argumentos de linha de comando
# Converte caminho dos diretórios para caminho absoluto
foreach my $dir (@ARGV){
$dir = abs_path( $dir );
if ( -d $dir ) {
push(@dirs, abs_path( $dir ));
next;
}
ERROR "Diretório $dir não existe ou não é um diretório.";
}
my %md5_hashes;
# Itera sobre todos os diretórios fornecidos
for my $dir (@dirs) {
# Aplica a função anônima a todos os arquivos e diretórios dentro de $dir
find(
sub {
# Ignora diretórios
return if -d;
# Obtém o caminho completo do arquivo atual
my $file_path = $File::Find::name;
# Calcula o valor de hash MD5 do arquivo atual
my $hash = file_md5_hex($file_path);
# Verifica se já encontramos um arquivo com o mesmo valor de hash antes (um arquivo duplicado)
if ( exists $md5_hashes{$hash} ) {
# Exclui o arquivo duplicado
INFO "Excluindo arquivo duplicado: $file_path";
unlink $file_path;
}
else {
# Armazena o valor de hash e o caminho do arquivo na tabela hash %md5_hashes
INFO "Mantendo o arquivo $file_path";
$md5_hashes{$hash} = $file_path;
}
},
$dir
);
}
}
sub file_md5_hex {
my ($file) = @_;
# Abre o arquivo em modo de leitura e binário
open( my $fh, '<', $file ) or die "Não foi possível abrir o arquivo: $!";
binmode($fh);
# Calcula o valor de hash MD5 do conteúdo do arquivo e o retorna no formato hexadecimal
return Digest::MD5->new->addfile($fh)->hexdigest;
}
sub print_usage {
print <<"EOF";
Uso: ./rm_duplicates dir_1 dir_2
Descrição: Remove arquivos duplicados em um ou mais diretórios. Se nenhum diretório é fornecido, o diretório atual é utilizado.
Opções:
--help Exibe esta mensagem de ajuda.
EOF
}
main();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment