Linux: Compare a estrutura de diretórios sem comparar arquivos

55

Qual é a melhor e mais simples maneira de comparar duas estruturas de diretório sem comparar os dados nos arquivos? Isso funciona bem:

diff -qr dir1 dir2_

Mas é muito lento porque também está comparando arquivos. Existe uma opção para diff ou outra ferramenta CLI simples para fazer isso?

Jonah
fonte
Por "estrutura de diretórios", você quer dizer apenas os caminhos do diretório ou os arquivos dos arquivos de diretório e não-diretório?
intuited
Sim, pastas e arquivos.
Jonah
11
Nesse caso, você deve remover a -type dopção da resposta de @ slartibartfast ou verificar minha resposta.
intuited

Respostas:

36

O seguinte (se você substituir o primeiro diretório por directory1 e o segundo por directory2) deve fazer o que procura rapidamente:

find directory1 -type d -printf "%P\n" | sort > file1
find directory2 -type d -printf "%P\n" | sort | diff - file1

O princípio fundamental é que ele imprima todos os diretórios, incluindo os caminhos dos subdiretórios em relação aos diretórios baseN do diretório.

Isso pode cair (produzir uma saída estranha) se você tiver retornos de carro em alguns nomes de diretório, mas não em outros.

Slartibartfast
fonte
Isso não é bom para mim, porque se um diretório contém uma pasta com alguns milhares de arquivos, todos são listados individualmente, enquanto diff -rqapenas mostra que o diretório raiz existe em um e continua.
21816 Chris Jefferson
Como fora pontiagudo (anos) por intuído, para responder à pergunta PO, o do tipo d devem ser removidos para que os arquivos são considerados na comparação, bem como diretórios
user2746401
Entendo e respeito essa leitura da declaração do problema. Essa não era a minha leitura na época. Você está recomendando que eu edite minha resposta para responder à pergunta atualizada? Estou bem fazendo isso se você acha que será útil para algumas pessoas, e estou bem deixando a solução e o comentário definidos como estão agora, o que parece ser razoavelmente eficaz.
Slartibartfast
34
vimdiff <(cd dir1; find . | sort) <(cd dir2; find . | sort)

fornecerá uma boa exibição lado a lado das duas hierarquias de diretório com as seções comuns dobradas.

garyjohn
fonte
Esta solução falha aleatoriamente. Quando o vim lê (ou relê) o descritor de arquivo temporário, ele já se foi.
Denilson Sá Maia
23

Eu costumo usar rsyncpara esta tarefa:

rsync -nav --delete DIR1/ DIR2

TENHA MUITO CUIDADO para sempre usar aopção-naka--dry-run, ou ele irá sincronizar (alterar o conteúdo dos) diretórios.

Isso comparará os arquivos com base nos tempos e tamanhos de modificação do arquivo ... Acho que é isso que você realmente deseja, ou pelo menos você não se importa se isso acontecer? Eu tenho a sensação de que você só quer que isso aconteça mais rápido , não que você precise ignorar a diferença entre o conteúdo do arquivo. Se você não listar arquivos diferentes com nomes idênticos, acho que a adição da --ignore-existingopção fará isso.

Lembre-se também de que não colocar um /no final de DIR1fará com que ele compare o diretório DIR1 com o conteúdo de DIR2.

A saída acaba sendo um pouco detalhada, mas mostrará quais arquivos / diretórios diferem. Os arquivos / diretórios presentes em DIR2e não em DIR1serão precedidos pela palavra deleting.

Em algumas situações, a resposta de @ slartibartfast pode ser mais apropriada, embora você precise remover a -type dopção para ativar a listagem de arquivos que não sejam de diretório. rsyncserá mais rápido se você tiver um número significativo de arquivos / diretórios para comparar.

intuído
fonte
Excelente resposta. Na saída do rsync, é difícil notar o deleting...texto, mas é provavelmente uma das melhores maneiras de comparar arquivos, mantendo a velocidade. Outras respostas aqui são mais rápidas quando arquivos diferentes não são necessários ... como no exemplo do OP, mas eu realmente gosto dessa.
Joel Mellon
Isto é o que eu estava procurando. Eu tinha alguns arquivos com tamanhos diferentes em um par enorme de árvores de diretório e queria saber quais. Isso alcançou esse objetivo em poucos segundos.
suprjami
Talvez seja uma boa ideia executá-lo com um usuário que tenha acesso somente leitura. Like sudo -u nobody rsync -nav --delete d1 d2desde que os sinalizadores para 'outros' permitam a leitura.
usar o seguinte comando
Ao executar esta solução, obtive a "lista de arquivos de construção ... concluída \ n enviada X bytes recebidos Y bytes Z bytes / s o tamanho total é A aceleração é B" (onde substituí XYZAB por números). Isso significa que tudo era idêntico? Desde que não mencionou nada mais específico? Agradecemos antecipadamente
Scott H
Para responder minha própria pergunta, experimentei adicionar arquivos diferentes a cada um, e parece que nenhum arquivo / diretório específico mencionado na saída significa que eles são todos iguais.
Scott H
18

Semelhante à resposta ls, mas se você instalar uma árvore , poderá

tree dir1 > out1
tree dir2 > out2
diff out1 out2
dígito
fonte
7
Ou para evitar os TMPFILES,diff <( tree dir1 ) <( tree dir2 )
Joel Mellon
11
Eu recomendo executar a árvore com a ibandeira, que não imprime as linhas das árvores ( tree -i dir1, etc). Se a estrutura de diretórios for diferente em um local, os outros arquivos correspondentes poderão ter mais ou menos |símbolos na saída da árvore, e o diff capturará essas linhas, mesmo que os caminhos dos arquivos sejam idênticos.
askewchan
2
diff <(árvore -i dir1) <(árvore -i dir2) é de longe a melhor resposta. Fico tentado a reduzir o voto de todas as respostas que sugerem diff ou rsync, pois a pergunta diz explicitamente NÃO para ler o conteúdo do arquivo. NOTA: A sugestão de usar dois tubos exige o uso cuidadoso de espaços entre parênteses, siga o exemplo exatamente. Por exemplo, para comparar dois volumes 20G após um backup, a resposta em árvore levou cerca de 5 segundos. Os outros levaram mais de 20 minutos.
Jason Morgan
3

Eu estava apenas procurando uma solução para este problema. A solução que mais gostei foi:

comm <(ls DIR1) <(ls DIR2)

Ele fornece três colunas: 1 - arquivos apenas em DIR1, 2 - arquivos apenas em DIR2, 3 - arquivos apenas em DIR3 Para obter mais detalhes, consulte esta postagem no blog.

kyrisu
fonte
Onde é DIR3especificado? Tudo o que vejo é DIR1e DIR2.
Michael Dorst
Eu tentei, e (pelo que eu posso dizer) a saída foi: todos os arquivos apenas em DIR1na coluna 1 , todos os arquivos somente em DIR2na coluna 2 , e todos os arquivos compartilhados por ambos na coluna 3 . Isso é útil, mas você sabe como remover a coluna 3 e deixar apenas as diferenças? Eu tenho muitos arquivos para classificar, e a maioria é idêntica. Eu não preciso ver o que é o mesmo.
quer
11
Além disso, descobri que comm <(ls DIR1) <(ls DIR2)não funcionava recursivamente. Para isso eu usei comm <(ls -R1 DIR1) <(ls -R1 DIR2). ls -Rrastreia pelos diretórios recursivamente e ls -1(observe que é um , não um L ) lsimprime apenas um nome de arquivo por linha.
Michael Dorst
@ Michael: comm -3(veja man comm).
Zaz
2
ls > dir1.txt

ls > dir2.txt

Depois, basta diferenciar as duas listas.

MDMarra
fonte
Parece que o OP quer uma hierarquia de caminhos. Isso diferirá todos os arquivos no diretório atual. É discutível, mas possível, que ele apenas queira diretórios; ele pode querer nomes de arquivos em vez do conteúdo dos arquivos.
intuited
@ intuited - você está certo. Eu interpretei errado.
MDMarra
2

Esta é a solução ideal

diff --brief -r dir1 dir2

--brief switch informa apenas se os arquivos diferem, não os detalhes da diferença.

jkshah
fonte
11
O OP já possui -qa pergunta, que é um apelido para --brief. Esta resposta não fornece nenhuma informação nova.
Michael Dorst
11
O OP não deseja a comparação do conteúdo do arquivo. But it's really slow because it's comparing files too.
Joel Mellon
1

use "diff -qr" para obter os diferentes arquivos e, em seguida, filtre a comparação de arquivos com o grep para obter apenas os nomes de arquivos que estão apenas em um dos diretórios.

diff -qr dir1 dir2 | grep -v "Files.*differ" 
Anônimo
fonte
1

Isso funcionou para a minha necessidade específica de encontrar arquivos ausentes nas árvores que correspondam.

diff <( cd dir1; find * |sort ) <(cd dir2; find * | sort)
amhest
fonte
-3

Eu acho que apenas rsync é userfull. porque?

diff é útil apenas para estruturas que mantêm arquivos e diretórios. Diff não fornece códigos de saída adequados quando usamos links simbólicos. Nessa situação, o diff pode retornar 2 códigos de saída, mesmo que src e dst sejam idênticos (horários, tamanhos, nomes, carimbos de data e hora, apontadores de links, etc).

dir, o sistema de arquivos não garante a ordem dos arquivos, mesmo que o conteúdo do diretório src e dst seja idêntico. Talvez você devesse filtrar a saída ls classificando-a. Mas ls puro exibe apenas nomes de nós.

talvez scripts que incluam diff, cmp, test -X para tipos de nó sejam úteis, mas lembre-se da sobrecarga causada por muitas execuções test / cmp. O script será muito lento.

Como de costume, se você quiser obter informações simples "dirs é / não é idêntico", você deve usar o rsync com a opção -n (dry). Se você quiser descobrir o que é diferente, use o comando diff.

Znik
fonte
Gostaria de saber por que menos?
Znik 10/03/16