Extrai arquivos idênticos de dois diretórios

0

Estou procurando uma solução Linux para o seguinte problema:

Dado dois diretórios com um grande número de arquivos. Todos os nomes de arquivos são aleatórios e diferentes nos dois diretórios. O conteúdo de alguns dos arquivos nos dois diretórios é idêntico, no entanto.

Eu quero copiar todos os arquivos que ocorrem em ambos os diretórios para um terceiro diretório. ("Ocorre em ambos" significa ter o mesmo conteúdo e não o mesmo nome.)

    
por Mel 14.03.2014 / 22:38

3 respostas

1

Supondo que seus nomes de arquivos não possuam nenhum espaço em branco e não haja subdiretórios em nenhum diretório, o seguinte imprimirá pares de nomes de arquivos com somas MD5 correspondentes:

join -o 1.2,2.2 <(md5sum $D1/* | sort) <(md5sum $D2/* | sort)

Para obter apenas um dos nomes de arquivo, use -o 1.2 ou -o 2.2 .

Se nomes de arquivos (ou caminhos) puderem incluir espaço em branco, você precisará ser mais esperto.

Se um único diretório puder ter o mesmo arquivo com mais de um nome, você também precisará ser mais inteligente - e precisará decidir exatamente o que fazer. Uma possibilidade seria filtrar as duplicatas antes de fazer a junção:

join -o 1.2,2.2 <(md5sum $D1/* | sort | uniq -w16) \
                <(md5sum $D2/* | sort | uniq -w16)

NÃO USE sum

sum gera uma soma de verificação de 16 bits; Se você tiver até mesmo algumas centenas de arquivos em cada diretório, é provável que obtenha um falso positivo se comparar somas de verificação de 16 bits. md5sum também não é absolutamente seguro, mas as chances de uma colisão com somas de verificação de 128 bits são pequenas. Em caso de dúvida, e se for realmente importante, cmp os arquivos também:

join -o 1.2,2.2 <(md5sum $D1/* | sort) <(md5sum $D2/* | sort) |
while read F1 F2; do
  if cmp -s $F1 $F2; then
    cp F1 $D3
  fi
done

(Novamente, isso não funcionará se os arquivos tiverem espaços em branco em seus nomes.)

    
por 15.03.2014 / 02:53
0

Usando seu shell favorito para esse pseudo código:

cd D1; sum * | while read l; do echo "D1 $l"; done >/tmp/foo
cd D2; sum * | while read l; do echo "D2 $1"; done >>/tmp/foo

sort -n /tmp/foo | awk '
$1 == prev_cs { echo "cp $3 dest"}
     /prev_cs = $1/
' | shell

Você pode salvar a saída do awk para revisão antes de emitir as cópias, se quiser

    
por 14.03.2014 / 23:18
0

isso pode fazer o trabalho, como com o ans do mpez0 para copiar os dups.

find {tst1,tst2} -exec sum {} {} \; 2> /dev/null | sort | uniq

    
por 15.03.2014 / 00:40