Linux: Comparer la structure des répertoires sans comparer les fichiers

55

Quel est le moyen le plus simple et le plus simple de comparer deux structures de répertoires sans comparer réellement les données contenues dans des fichiers? Cela fonctionne bien:

diff -qr dir1 dir2_

Mais c'est vraiment lent parce que c'est aussi comparer des fichiers. Existe-t-il un commutateur pour diff ou un autre outil simple cli pour le faire?

Jonas
la source
Par "structure de répertoire", entendez-vous uniquement les chemins de répertoire, ou les chemins des fichiers de répertoire et des fichiers autres que de répertoire?
Intuition le
Oui, les dossiers et les fichiers.
Jonah
1
Dans ce cas, vous devez supprimer l' -type doption de la réponse de @ slartibartfast ou consulter ma réponse.
Intuition le

Réponses:

36

Ce qui suit (si vous substituez le premier répertoire pour directory1 et le second pour directory2) devrait faire ce que vous cherchez et rapidement:

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

Le principe fondamental est qu'il imprime tous les répertoires, y compris les chemins de sous-répertoires, par rapport aux répertoires de baseN.

Cela pourrait tomber (produire une sortie bizarre) si vous aviez des retours à la ligne dans certains noms de répertoires mais pas dans d’autres.

Slartibartfast
la source
Ce n'est pas bon pour moi, parce que si un répertoire contient un dossier avec quelques milliers de fichiers, ils sont tous listés individuellement, alors diff -rqqu'il indique simplement que le répertoire racine existe en un et continue.
Chris Jefferson
Comme indiqué (il y a des années) par intuited, pour répondre à la question des PO, le type-d devrait être supprimé afin que les fichiers soient pris en compte dans la comparaison ainsi que les répertoires
utilisateur2746401
Je comprends et respecte cette lecture de l'énoncé du problème. Ce n'était pas ma lecture à l'époque. Recommandez-vous que je modifie ma réponse pour répondre à la question mise à jour? Je peux le faire si vous pensez que cela sera utile pour certaines personnes, et je peux laisser la solution et les commentaires tels qu'ils sont, ce qui semble être relativement efficace.
Slartibartfast
34
vimdiff <(cd dir1; find . | sort) <(cd dir2; find . | sort)

vous donnera un bon affichage côte à côte des deux hiérarchies de répertoires avec toutes les sections communes repliées.

Garyjohn
la source
Cette solution échoue au hasard. Lorsque vim lit (ou relit) le descripteur de fichier temporaire, il est déjà parti.
Denilson Sá Maia
23

J'utilise habituellement rsyncpour cette tâche:

rsync -nav --delete DIR1/ DIR2

SOYEZ TRÈS ATTENTION à toujours utiliser l’option-n, autrement dit--dry-run, sinon cela synchronisera (changera le contenu des) répertoires.

Cela permettra de comparer les fichiers en fonction de la taille et du temps de modification des fichiers ... Je pense que c'est ce que vous voulez vraiment, ou du moins que cela ne vous dérange pas. J'ai l'impression que vous voulez simplement que cela se produise plus rapidement , sans que vous ayez besoin d'ignorer la différence entre le contenu du fichier. Si vous ne voulez pas que la liste des fichiers avec des noms identiques diffère, je pense que l’ajout de cette --ignore-existingoption le fera.

Sachez également que ne pas mettre un /à la fin de le DIR1fera comparer le répertoire DIR1 au contenu de DIR2.

La sortie finit par être un peu verbeuse, mais elle vous indiquera quels fichiers / répertoires diffèrent. Les fichiers / répertoires présents dans DIR2et non dans DIR1seront précédés du mot deleting.

Dans certaines situations, la réponse de @ slartibartfast peut être plus appropriée, bien que vous deviez supprimer l' -type doption permettant d'activer la liste des fichiers autres que des répertoires. rsyncsera plus rapide si vous avez un nombre significatif de fichiers / répertoires à comparer.

intuitif
la source
Excellente réponse. Dans la sortie de rsync, il est difficile de remarquer le deleting...texte, mais c’est probablement l’un des meilleurs moyens de comparer des fichiers tout en maintenant la vitesse. Les autres réponses ici sont plus rapides lorsqu'il n'est pas nécessaire de différencier les fichiers ... comme dans l'exemple d'OP, mais j'aime beaucoup celui-ci.
Joel Mellon
C'est ce que j'étais après. J'avais des fichiers de tailles différentes dans une énorme paire d'arbres de répertoires et je voulais savoir lesquels. Cet objectif a été atteint en quelques secondes seulement.
suprjami
C'est peut-être une bonne idée de l'exécuter avec un utilisateur disposant d'un accès en lecture seule. Comme à sudo -u nobody rsync -nav --delete d1 d2condition que les drapeaux pour 'autres' permettent la lecture.
user1182474
Lors de l’exécution de cette solution, j’ai reçu la "liste de fichiers de construction ... terminée \ n envoyé X octets reçus Y octets Z taille totale en octets / s est Une accélération est B" (où j'ai substitué XYZAB aux nombres). Est-ce que cela signifie que tout était identique? Puisqu'il n'a rien mentionné de plus spécifique? Merci d'avance
Scott H
Pour répondre à ma propre question, j’ai essayé d’ajouter différents fichiers dans chacun d’entre eux, et il apparaît qu’aucun fichier / répertoire spécifique mentionné dans la sortie ne signifie qu’ils sont tous identiques.
Scott H
18

Semblable à la réponse de ls mais si vous installez l’ arbre, vous pouvez

tree dir1 > out1
tree dir2 > out2
diff out1 out2
chiffre
la source
7
Ou pour éviter les tmpfiles,diff <( tree dir1 ) <( tree dir2 )
Joel Mellon
1
Je recommande d'exécuter tree avec le idrapeau, qui n'imprime pas les lignes de l'arbre ( tree -i dir1, etc.). Si la structure du répertoire est différente à un endroit, les autres fichiers qui correspondent peuvent avoir plus ou moins de |symboles dans la sortie de l'arborescence, et diff interceptera ces lignes même si les chemins d'accès aux fichiers sont identiques.
askewchan
2
diff <(tree -i dir1) <(tree -i dir2) est de loin la meilleure réponse. Je suis tenté de réduire toutes les réponses suggérant diff ou rsync car la question dit explicitement de ne PAS lire le contenu du fichier. REMARQUE: La suggestion d'utiliser deux tuyaux nécessite une utilisation prudente des espaces entre crochets, suivez exactement l'exemple. Par exemple, pour comparer deux volumes 20G après une sauvegarde, la réponse de l'arborescence a pris environ 5 secondes. Les autres ont pris plus de 20 minutes.
Jason Morgan
3

Je cherchais simplement une solution à ce problème. La solution qui m'a le plus plu était:

comm <(ls DIR1) <(ls DIR2)

Il vous donne 3 colonnes: 1 - fichiers uniquement dans DIR1, 2 - fichiers uniquement dans DIR2, 3 - fichiers uniquement dans DIR3. Pour plus de détails, consultez cet article de blog.

kyrisu
la source
Où est DIR3spécifié? Tout ce que je vois est DIR1et DIR2.
Michael Dorst
Je l' ai essayé, et (de ce que je peux dire) la sortie est: tous les fichiers que dans DIR1dans la colonne 1 , tous les fichiers que dans DIR2dans la colonne 2 , et tous les fichiers partagés par les deux dans la colonne 3 . C'est en quelque sorte utile, mais savez-vous comment on pourrait supprimer la colonne 3 et ne laisser que les différences? J'ai beaucoup de fichiers à trier et la plupart sont identiques. Je n'ai pas besoin de voir ce qui est pareil.
Michael Dorst
1
En outre, j'ai trouvé que comm <(ls DIR1) <(ls DIR2)cela ne fonctionnait pas de manière récursive. Pour cela j'ai utilisé comm <(ls -R1 DIR1) <(ls -R1 DIR2). ls -Rparcourt les répertoires de manière récursive et ls -1(notez qu'il s'agit d'un seul , pas d'un L ) lsn'imprime qu'un seul nom de fichier par ligne.
Michael Dorst
@ Michael: comm -3(voir man comm).
Zaz
2
ls > dir1.txt

ls > dir2.txt

Ensuite, diff juste les deux listes.

MDMarra
la source
On dirait que le PO veut une hiérarchie de chemins. Cela va différer tous les fichiers du répertoire courant. C'est discutable, mais possible, qu'il veut juste des répertoires; il peut vouloir des noms de fichiers plutôt que le contenu des fichiers.
Intuition le
@ intuitif - vous avez raison. Je l'ai mal lu.
MDMarra
2

C'est la solution optimale

diff --brief -r dir1 dir2

--brief switch indique uniquement si les fichiers diffèrent, pas les détails de la différence.

jkshah
la source
1
Le PO a déjà -qdans la question, qui est un alias pour --brief. Cette réponse ne fournit aucune nouvelle information.
Michael Dorst
1
OP ne veut pas la comparaison du contenu du fichier. But it's really slow because it's comparing files too.
Joel Mellon
1

utilisez "diff -qr" pour obtenir les différents fichiers, puis filtrez la comparaison de fichiers avec grep afin de n'obtenir que les noms de fichiers ne figurant que dans l'un des répertoires.

diff -qr dir1 dir2 | grep -v "Files.*differ" 
Anonyme
la source
1

Cela a fonctionné pour mon besoin spécifique de trouver des fichiers manquants dans les arbres censés correspondre.

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

Je pense que seul rsync est utilisateur. Pourquoi?

diff est utile uniquement pour les structures conservant des fichiers et des répertoires. Diff ne donne pas les codes de sortie adéquats lorsque nous utilisons des liens symboliques. Dans cette situation, diff peut renvoyer 2 codes de sortie, même si src et dst sont identiques (heures, tailles, noms, horodatages, liens symboliques de pointage, etc.).

dir, le système de fichiers ne garantit pas le classement des fichiers, même si le contenu du répertoire sur src et dst est identique. Peut-être devriez-vous filtrer la sortie ls en la triant. Mais pure ls n'affiche que les noms de nœuds.

Peut-être qu'un script incluant diff, cmp, test -X pour les types de nœuds sera utile, mais souvenez-vous de la surcharge générée par de nombreux tests / cmp. Le script sera très lent.

Comme d'habitude, si vous voulez obtenir des informations simples "les répertoires sont / n'est pas identiques", vous devez utiliser rsync avec l'option -n (dry). Si vous voulez trouver ce qui est différent, utilisez la commande diff.

Znik
la source
Je voudrais savoir pourquoi les inconvénients?
Znik