Last active
June 13, 2023 22:54
-
-
Save viniciusgonmelo/5a015306e7c4b605082a666dea7e1491 to your computer and use it in GitHub Desktop.
Remove arquivos duplicados em um ou mais diretórios
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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