Esta é uma parte modificada da resposta que escrevi ontem :
$ cksum file* | awk '{ ck[$1$2] = ck[$1$2] ? ck[$1$2] ", " $3 : $3 } END { for (i in ck) print ck[i] }'
file3, file5
file1, file2, file4
No seu caso, você usaria *.txt
ou mesmo *
(se tudo o que você tem no diretório é o arquivo que deseja comparar), em vez de file*
.
O resultado informa que file3
e file5
têm o mesmo conteúdo, como file1
, file2
e file4
(neste exemplo).
O utilitário padrão cksum
exibirá três colunas para cada arquivo. A primeira é uma soma de verificação, a segunda é um tamanho de arquivo e a terceira é um nome de arquivo.
O código awk
usará a soma de verificação e o tamanho como uma chave na matriz ck
e armazenará os nomes dos arquivos que tiverem a mesma chave em uma string separada por vírgula para essa chave. No final, os nomes dos arquivos (seqüência separada por vírgula) são impressos.
A aparência engraçada
ck[$1$2] = ck[$1$2] ? ck[$1$2] ", " $3 : $3
significa apenas "se ck[$1$2]
estiver definido como qualquer coisa, atribua ck[$1$2] ", " $3
a ck[$1$2]
(anexando um nome de arquivo com uma vírgula intermediária), caso contrário, atribua $3
(é o primeiro nome de arquivo com essa chave ) ".
Para classificar a saída no número de itens em cada lista, passe a saída por
awk -F, '{ print NF, $0 }' | sort -n | cut -d ' ' -f 2-
... como um estágio de pós-processamento. Isso obviamente irá quebrar se qualquer nome de arquivo contiver uma vírgula.
Ou use
cksum file* | awk '{ n[$1$2]++; ck[$1$2] = ck[$1$2] ? ck[$1$2] ", " $3 : $3 } END { for (i in ck) print n[i], ck[i] }' | sort -n | cut -d ' ' -f 2-
que não tem problemas com vírgulas em nomes de arquivos.
Deixe o cut
out se quiser ver o número de nomes de arquivos em cada linha de saída.
Para um grande número de arquivos, você pode querer usar
find . -type f -exec cksum {} +
em vez de apenas
cksum *