Baixei muitas imagens em um diretório.
Downloader renomeou arquivos que já existem.
Também renomeei alguns dos arquivos manualmente.
a.jpg
b.jpg
b(2).jpg
hello.jpg <-- manually renamed `b(3).jpg`
c.jpg
c(2).jpg
world.jpg <-- manually renamed `d.jpg`
d(2).jpg
d(3).jpg
Como remover os duplicados? O resultado deve ser:
a.jpg
b.jpg
c.jpg
world.jpg
nota: o nome não importa. Eu só quero arquivos uniq.
Responder1
bash 4.x
#!/bin/bash
declare -A arr
shopt -s globstar
for file in **; do
[[ -f "$file" ]] || continue
read cksm _ < <(md5sum "$file")
if ((arr[$cksm]++)); then
echo "rm $file"
fi
done
Isso é recursivo e lida com qualquer nome de arquivo. A desvantagem é que ela requer a versão 4.x para poder usar matrizes associativas e pesquisa recursiva. Remova o echo
se você gostar dos resultados.
versão boquiaberta
gawk '
{
cmd="md5sum " q FILENAME q
cmd | getline cksm
close(cmd)
sub(/ .*$/,"",cksm)
if(a[cksm]++){
cmd="echo rm " q FILENAME q
system(cmd)
close(cmd)
}
nextfile
}' q='"' *
Observe que isso ainda será interrompido em arquivos que possuem aspas duplas em seus nomes. Não há maneira real de contornar isso com awk
. Remova o echo
se você gostar dos resultados.
Responder2
fdupesé a ferramenta de sua escolha. Para localizar todos os arquivos duplicados (por conteúdo, não por nome) no diretório atual:
fdupes -r .
Para confirmar manualmente a exclusão de arquivos duplicados:
fdupes -r -d .
Para excluir automaticamente todas as cópias, exceto a primeira de cada arquivo duplicado (esteja avisado, este aviso, isso realmente exclui arquivos, conforme solicitado):
fdupes -r -f . | grep -v '^$' | xargs rm -v
Eu recomendo verificar manualmente os arquivos antes de excluí-los:
fdupes -rf . | grep -v '^$' > files
... # check files
xargs -a files rm -v
Responder3
Eu recomendoclones.
Fclones é um moderno localizador e removedor de arquivos duplicados escrito em Rust, disponível na maioria das distribuições Linux e macOS.
Recursos notáveis:
- suporta espaços, caracteres não-ASCII e de controle em caminhos de arquivo
- permite pesquisar em múltiplas árvores de diretórios
- respeita arquivos .gitignore
- seguro: permite inspecionar a lista de duplicatas manualmente antes de realizar qualquer ação sobre elas
- oferece muitas opções para filtrar/selecionar arquivos para remover ou preservar
- muito rápido
Para procurar duplicatas no diretório atual, basta executar:
fclones group . >dupes.txt
Em seguida, você pode inspecionar o dupes.txt
arquivo para verificar se encontrou as duplicatas corretas (você também pode modificar essa lista ao seu gosto).
Por fim, remova/vincule/mova os arquivos duplicados com um dos seguintes:
fclones remove <dupes.txt
fclones link <dupes.txt
fclones move target <dupes.txt
fclones dedupe <dupes.txt # copy-on-write deduplication on some filesystems
Exemplo:
pkolaczk@p5520:~/Temp$ mkdir files
pkolaczk@p5520:~/Temp$ echo foo >files/foo1.txt
pkolaczk@p5520:~/Temp$ echo foo >files/foo2.txt
pkolaczk@p5520:~/Temp$ echo foo >files/foo3.txt
pkolaczk@p5520:~/Temp$ fclones group files >dupes.txt
[2022-05-13 18:48:25.608] fclones: info: Started grouping
[2022-05-13 18:48:25.613] fclones: info: Scanned 4 file entries
[2022-05-13 18:48:25.613] fclones: info: Found 3 (12 B) files matching selection criteria
[2022-05-13 18:48:25.614] fclones: info: Found 2 (8 B) candidates after grouping by size
[2022-05-13 18:48:25.614] fclones: info: Found 2 (8 B) candidates after grouping by paths and file identifiers
[2022-05-13 18:48:25.619] fclones: info: Found 2 (8 B) candidates after grouping by prefix
[2022-05-13 18:48:25.620] fclones: info: Found 2 (8 B) candidates after grouping by suffix
[2022-05-13 18:48:25.620] fclones: info: Found 2 (8 B) redundant files
pkolaczk@p5520:~/Temp$ cat dupes.txt
# Report by fclones 0.24.0
# Timestamp: 2022-05-13 18:48:25.621 +0200
# Command: fclones group files
# Base dir: /home/pkolaczk/Temp
# Total: 12 B (12 B) in 3 files in 1 groups
# Redundant: 8 B (8 B) in 2 files
# Missing: 0 B (0 B) in 0 files
6109f093b3fd5eb1060989c990d1226f, 4 B (4 B) * 3:
/home/pkolaczk/Temp/files/foo1.txt
/home/pkolaczk/Temp/files/foo2.txt
/home/pkolaczk/Temp/files/foo3.txt
pkolaczk@p5520:~/Temp$ fclones remove <dupes.txt
[2022-05-13 18:48:41.002] fclones: info: Started deduplicating
[2022-05-13 18:48:41.003] fclones: info: Processed 2 files and reclaimed 8 B space
pkolaczk@p5520:~/Temp$ ls files
foo1.txt
Responder4
Como testar arquivos com conteúdo exclusivo?
if diff "$file1" "$file2" > /dev/null; then
...
Como podemos obter uma lista de arquivos no diretório?
files="$( find ${files_dir} -type f )"
Podemos obter 2 arquivos quaisquer dessa lista e verificar se seus nomes são diferentes e o conteúdo é o mesmo.
#!/bin/bash
# removeDuplicates.sh
files_dir=$1
if [[ -z "$files_dir" ]]; then
echo "Error: files dir is undefined"
fi
files="$( find ${files_dir} -type f )"
for file1 in $files; do
for file2 in $files; do
# echo "checking $file1 and $file2"
if [[ "$file1" != "$file2" && -e "$file1" && -e "$file2" ]]; then
if diff "$file1" "$file2" > /dev/null; then
echo "$file1 and $file2 are duplicates"
rm -v "$file2"
fi
fi
done
done
Por exemplo, temos algum diretório:
$> ls .tmp -1
all(2).txt
all.txt
file
text
text(2)
Portanto, existem apenas 3 arquivos exclusivos.
Vamos executar esse script:
$> ./removeDuplicates.sh .tmp/
.tmp/text(2) and .tmp/text are duplicates
removed `.tmp/text'
.tmp/all.txt and .tmp/all(2).txt are duplicates
removed `.tmp/all(2).txt'
E temos apenas 3 arquivos restantes.
$> ls .tmp/ -1
all.txt
file
text(2)