Étant donné deux arborescences de répertoires, comment savoir quels fichiers diffèrent par leur contenu?

786

Si je veux trouver les différences entre deux arborescences de répertoires, j'exécute généralement simplement:

diff -r dir1/ dir2/

Cela génère exactement les différences entre les fichiers correspondants. Je souhaite simplement obtenir une liste des fichiers correspondants dont le contenu diffère. J'ai supposé que ce serait simplement une question de passer une option de ligne de commande à diff, mais je n'ai rien trouvé sur la page de manuel.

Aucune suggestion?

Mansoor Siddiqui
la source
1
En ce qui concerne l'un des répertoires, comment obtenir uniquement les fichiers / répertoires qui sont supplémentaires dans l'autre?
Sandeepan Nath
utiliser la dircmpcommande sur unix (pas linux)
roblogic

Réponses:

1119

Vous avez dit Linux, alors vous avez de la chance (au moins, il devrait être disponible, vous ne savez pas quand il a été ajouté):

diff --brief --recursive dir1/ dir2/ # GNU long options
diff -qr dir1/ dir2/ # common short options

Devrait faire ce dont vous avez besoin.

Si vous souhaitez également voir les différences pour les fichiers qui peuvent ne pas exister dans l'un ou l'autre répertoire:

diff --brief --recursive --new-file dir1/ dir2/ # GNU long options
diff -qrN dir1/ dir2/ # common short options
Mark Loeser
la source
12
Agréable. Mais plus court est diff -qr dir1/ dir2/et ma version étendue àdiff -qr dir1/ dir2/ | grep ' differ'
sobi3ch
1
@skv pourquoi? C'est la même commande que la réponse. Je n'ai changé que --briefpour son raccourci -q.
sobi3ch
2
@skv Pas exactement ce que la question d'origine a demandé, mais la mise à jour de la réponse pour répondre à cette question également.
Mark Loeser
3
@MikeMaxwell Cela doit être --brief. -briefest interprété comme -b -r -i -e -f, en d'autres termes, comme un ensemble de drapeaux et non comme une seule option.
daboross
2
@daboross: wow, j'utilise Unix / Linux depuis longtemps, et je n'ai jamais réalisé qu'il y avait cette distinction entre '-' et '-'. (Je ne pense pas que '-' existait quand j'ai commencé.) Merci pour l'explication!
Mike Maxwell
287

La commande que j'utilise est:

diff -qr dir1/ dir2/

C'est exactement le même que celui de Mark :) Mais sa réponse m'a dérangé car il utilise différents types de drapeaux, et cela m'a fait regarder deux fois. En utilisant les drapeaux les plus verbeux de Mark, ce serait:

diff  --brief --recursive dir1/ dir2/

Je m'excuse d'avoir posté lorsque l'autre réponse est parfaitement acceptable. Je ne pouvais pas m'empêcher ... de travailler pour être moins pédant.

FPC
la source
3
appréciez totalement la cohérence - mais ne vous sentez pas mal; J'ai aussi voté pour la réponse de Mark;)
Gerard ONeill
10
..est-il donc logique de mettre des réponses différentes avec JUSTE une saveur différente? À mon humble avis non! Est-il sensé de combiner les deux réponses en une seule réponse cohérente? Oui! ;)
sobi3ch
1
Juste une question; que signifie le qstand? Est-ce une abréviation de quelque chose? Je ne trouve aucune logique derrière le q..
kramer65
3
@ kramer65 - c'est la même chose que "--brief", mais je suppose que vous vous demandez pourquoi q? Peut-être pour vite? "-b" est pris par "ignorer les changements dans la quantité d'espace blanc" selon la page de manuel.
FPC
4
@ kramer65 Je crois que qc'est pour quiet, ce qui signifie généralement moins verbeux.
Gogeta70
105

J'aime utiliser git diff --no-index dir1/ dir2/, car il peut montrer les différences de couleur (si cette option est définie dans votre configuration git) et parce qu'il montre toutes les différences dans une sortie paginée longue en utilisant "moins".

Alan Porter
la source
25
Soigné. Qui aurait pu deviner que git peut différencier des répertoires arbitraires, pas seulement le dépôt contre ses fichiers?
Dan Dascalescu
2
Le script Perl colordiff est très utile ici, peut être utilisé avec svn et diff normal.
Felipe Alvarez
4
Si vous comparez (comme moi) 2 dirs en tant que projets / repos git séparés, vous devez en ajouter --no-indexplus sur stackoverflow.com/a/1792477/473390 . J'ai mis à jour la réponse @ alan-porter.
sobi3ch
J'aime celui-ci, je trouve également que si vous ajoutez --name-status à la ligne de commande, il affichera simplement la liste des noms de fichiers avec des drapeaux "M / A / D" pour le statut Modifié / Ajouté / Supprimé.
gzh
Il arrive que les deux répertoires contiennent réellement le dossier .git, comment puis-je l'exclure de la comparaison?
Muhamed Cicak
35

Ces deux commandes font essentiellement la chose demandée:

diff --brief --recursive --no-dereference --new-file --no-ignore-file-name-case /dir1 /dir2 > dirdiff_1.txt

rsync --recursive --delete --links --checksum --verbose --dry-run /dir1/ /dir2/ > dirdiff_2.txt

Le choix entre eux dépend de l'emplacement de dir1 et dir2:

Lorsque les répertoires résident sur deux lecteurs séparés, diff surpasse rsync. Mais lorsque les deux répertoires comparés se trouvent sur le même lecteur, rsync est plus rapide. C'est parce que diff met une charge presque égale sur les deux répertoires en parallèle, maximisant la charge sur les deux disques.

rsync calcule les sommes de contrôle en gros morceaux avant de réellement les comparer. Cela regroupe les opérations d'E / S en gros morceaux et conduit à un traitement plus efficace lorsque les choses se déroulent sur un seul disque.

CodeBug
la source
3
rsync est non seulement plus rapide pour les fichiers sur des disques uniques, mais permet également de comparer les fichiers dans les sous-répertoires, par exemple rsync --options /usr /bin /var /sbin /lib /old_root, comparera efficacement la racine actuelle /(en spécifiant tous les sous-répertoires) et /old_root(contenant par exemple une sauvegarde plus ancienne de /), ce qui est quelque chose qui diff -rpeut ne fais pas. Et si vous supposez que les fichiers de même taille, d'autorisations et d'horodatages n'ont probablement pas changé, le fait de laisser de côté --checksumvous fournira une vérification extrêmement rapide (si ce n'est pas le cas) des fichiers qui ont pu être modifiés.
Matija Nalis
1
Quel est le but de --deleteavec rsync?
Tom Hale
2
Le but de --delete est de supprimer les fichiers existants dans le répertoire de destination qui ne sont (plus) présents dans le répertoire source
Thomas Munk
2
Dans ce cas (avec le --dry-rundrapeau) rien n'est vraiment supprimé, rsyncimprime uniquement les fichiers qui sont en dir1 mais pas en dir2
mata
11
Je recommanderais de mettre --dry-runtoujours le premier pour ne pas l'oublier accidentellement.
Dave Rager
22

Meld est également un excellent outil pour comparer deux répertoires:

meld dir1/ dir2/

Meld propose de nombreuses options pour comparer des fichiers ou des répertoires. Si deux fichiers diffèrent, il est facile d'entrer en mode de comparaison de fichiers et de voir les différences exactes.

Alexandre
la source
2
Agréable. J'ai écrit un simple script perl pour effectuer une comparaison sur les arbres mais je rencontre des limitations. Cela semble être le ticket.
David Tonhofer
Le seul problème est qu'il ne se prête pas aux scripts puisqu'il s'agit d'une application graphique. Mais c'est bien si cela ne vous dérange pas l'interface graphique! Merci.
DeanM
Je trouve que cela melddevient horriblement lent si utilisé sur de grands répertoires. Y a-t-il quelque chose qui gère mieux les grands répertoires?
Popup
@Popup, pas que je sache. Vous pouvez trouver des noms de fichiers différents avec quelque chose comme ça, cependant:find dir1 dir2 | cut -d/ -f2- | sort | uniq --unique
Alexander
1
@Alexander - Dans ce cas, je trouve que cela meld <(find dir1 -ls ) <(find dir2 -ls)fonctionne assez bien, en utilisant la substitution de processus bash. (zsh =(command)fonctionne encore mieux.)
Popup
10

'Billings', compatriote de la chaîne (de renommée freenode / # centos) a partagé sa méthode avec moi:

diff -Naur dir1/ dir2

L'inclusion de la barre oblique finale du répertoire n'a pas d'importance.

Il semble également que -u option ne soit pas disponible sur certaines versions plus anciennes / serveur de diff.

La différence de diffs:

# diff -Nar /tmp/dir1 /tmp/dir2/
diff -Nar /tmp/dir1/file /tmp/dir2/file
28a29
> TEST

# diff -qr /tmp/dir1/ /tmp/dir2/
Files /tmp/dir1/file and /tmp/dir2/file differ
todd_dsm
la source
2
C'est donc ce --new-file/-Nqui fait que diff considère que les fichiers manquants sont vides et --text/-aqui le fait considérer toutes les entrées binaires comme du texte. Je ne vois pas les avantages de ce cas d'utilisation particulier.
phk
4

Diffoscope est un excellent outil de annuaire basé sur la ligne de commande.

J'aime particulièrement le fait qu'il puisse différer en fichiers:

Il décompressera de manière récursive des archives de nombreux types et transformera divers formats binaires en une forme plus lisible par l'homme pour les comparer. Il peut comparer deux tarballs, images ISO ou PDF tout aussi facilement.

Il vous indiquera non seulement quels fichiers diffèrent, mais aussi comment ils diffèrent.

nh2
la source
4

Pour trouver diff, utilisez cette commande:

diff -qr dir1/ dir2/

-r diffère également tous les sous-répertoires -q indique à diff de ne signaler que lorsque les fichiers diffèrent.

diff  --brief dir1/ dir2/

--brief montrera les fichiers qui existent dans le répertoire.

Ou sinon

nous pouvons utiliser Meld qui montrera dans la fenêtre graphique qu'il est facile de trouver la différence.

meld  dir1/ dir2/
Javeed Shakeel
la source
2
--briefet -qsont la même option. Votre déclaration donne l'impression qu'ils sont différents, mais ils ne le sont pas.
Elijah Lynn
2

Vous pouvez également utiliser Rsyncet find. Pour find:

find $FOLDER -type f | cut -d/ -f2- | sort > /tmp/file_list_$FOLDER

Mais les fichiers avec les mêmes noms et dans les mêmes sous-dossiers, mais avec un contenu différent, ne seront pas affichés dans les listes.

Si vous êtes un fan de GUI, vous pouvez vérifier Meld que @Alexander a mentionné. Cela fonctionne très bien sous Windows et Linux.

Fábio
la source
1

Pour signaler les différences entre dirA et dirB, tout en mettant à jour / synchroniser.

rsync -auv <dirA> <dirB>

Kickaha
la source