diff pour afficher uniquement les noms de fichiers

244

Je cherche à exécuter une commande Linux qui comparera récursivement deux répertoires et ne produira que les noms de fichiers de ce qui est différent. Cela inclut tout ce qui est présent dans un répertoire et non l'autre ou vice versa, et les différences de texte.

barfoon
la source

Réponses:

376

Depuis la page de manuel diff:

-q   Indiquez uniquement si les fichiers diffèrent, et non les détails des différences.
-r   Lorsque vous comparez des répertoires, comparez récursivement tous les sous-répertoires trouvés.

Exemple de commande:

diff -qr dir1 dir2

Exemple de sortie (dépend des paramètres régionaux):

$ ls dir1 dir2
dir1:
same-file  different  only-1

dir2:
same-file  different  only-2
$ diff -qr dir1 dir2
Files dir1/different and dir2/different differ
Only in dir1: only-1
Only in dir2: only-2
John Kugelman
la source
Merci - la diffpage de manuel de CentOS 7 décrit -qcomme "signaler uniquement lorsque les fichiers diffèrent", ce qui est moins clair que ce que vous avez écrit.
Chap
2
Cela compare le contenu réel des fichiers, ce qui est souvent ce que l'on veut, cependant, la réponse rsync donne la possibilité de ne regarder que les noms et tailles de fichiers, et non le contenu; c'est parfois souhaitable.
steveb
Fonctionne également sur macOS.
Marius Soutier
Peut également inclure -x PATTERNdans la commande pour exclure certains sous-répertoires. Par exemple, diff -qr repo1 repo2 -x ".git" comparera deux répertoires mais exclura les chemins d'accès aux fichiers contenant ".git".
ViFI
27

Vous pouvez également utiliser rsync

rsync -rv --size-only --dry-run /my/source/ /my/dest/ > diff.out
boksiora
la source
6
--size-onlyil manquera des fichiers de taille identique mais de contenu différent, par exemple ancien / version.txt "29a" nouveau / version.txt "29b" . Utilisez à la place: rsync -ric --dry-run old/ new/où l'argument "-i" permet d'obtenir la liste des fichiers directement viarsync -ric --dry-run old/ new/ | cut -d" " -f 2
iolsmit
6
C'est génial si vous recherchez uniquement des fichiers manquants (en particulier sur les partages réseau), car cela ne compare pas le contenu. Cela m'a aidé à trouver quelques fichiers qui ont échoué lors de la migration vers un nouveau NAS.
OverZealous
4
Assurez-vous d'inclure la barre oblique de fin pour les chemins spécifiés sur la ligne de commande de rsync. Sans eux, cela ne fonctionnera pas correctement, et rsync énumérera probablement tous les noms de fichiers!
Vladimir Panteleev
2
En ce qui concerne les commentaires sur la non vérification du contenu. Ceci est parfois souhaitable, au moins lors de la première passe.
steveb
13

Si vous souhaitez obtenir une liste de fichiers qui ne se trouvent que dans un seul répertoire et non leurs sous-répertoires et uniquement leurs noms de fichiers:

diff -q /dir1 /dir2 | grep /dir1 | grep -E "^Only in*" | sed -n 's/[^:]*: //p'

Si vous souhaitez répertorier récursivement tous les fichiers et répertoires qui sont différents avec leurs chemins d'accès complets:

diff -rq /dir1 /dir2 | grep -E "^Only in /dir1*" | sed -n 's/://p' | awk '{print $3"/"$4}'

De cette façon, vous pouvez appliquer différentes commandes à tous les fichiers.

Par exemple, je pourrais supprimer tous les fichiers et répertoires qui se trouvent dans dir1 mais pas dir2:

diff -rq /dir1 /dir2 | grep -E "^Only in /dir1*" | sed -n 's/://p' | awk '{print $3"/"$4}' xargs -I {} rm -r {}
ND
la source
9

Sur mon système Linux pour obtenir uniquement les noms de fichiers

diff -q /dir1 /dir2|cut -f2 -d' '
gerardw
la source
7
Je ne mets pas de noms de fichiers avec des espaces sur mon système Linux. ;)
gerardw
6
Je ne voulais pas vous imputer cela ... ;-p Juste un indice pour quelqu'un qui le fait ...
michuelnik
ne fonctionne pas pour moi. Ma structure de répertoire est comme ciaudit-0.0.234/audit-data-warehouse-0.0.234/ audit-0.0.235/audit-data-warehouse-0.0.235/
Alex Raj Kaliamoorthy
diff -qrN /dir1 /dir2 | cut -f2 -d' 'fonctionne bien pour moi!
Francesco
9

L'approche de l'exécution diff -qr old/ new/a un inconvénient majeur: il peut manquer des fichiers dans des répertoires nouvellement créés. Par exemple, dans l'exemple ci-dessous, le fichier data/pages/playground/playground.txtn'est pas dans la sortie de diff -qr old/ new/tandis que le répertoire l' data/pages/playground/est (recherchez aire de jeux.txt dans votre navigateur pour comparer rapidement). J'ai également posté la solution suivante sur Unix et Linux Stack Exchange , mais je la copierai ici également:

Pour créer une liste de fichiers nouveaux ou modifiés par programme, la meilleure solution que j'ai pu trouver consiste à utiliser rsync , sort et uniq :

(rsync -rcn --out-format="%n" old/ new/ && rsync -rcn --out-format="%n" new/ old/) | sort | uniq

Je m'explique avec cet exemple: nous voulons comparer deux versions de dokuwiki pour voir quels fichiers ont été modifiés et lesquels ont été nouvellement créés.

Nous récupérons les goudrons avec wget et les extrayons dans les répertoires old/et new/:

wget http://download.dokuwiki.org/src/dokuwiki/dokuwiki-2014-09-29d.tgz
wget http://download.dokuwiki.org/src/dokuwiki/dokuwiki-2014-09-29.tgz
mkdir old && tar xzf dokuwiki-2014-09-29.tgz -C old --strip-components=1
mkdir new && tar xzf dokuwiki-2014-09-29d.tgz -C new --strip-components=1

L'exécution de rsync dans un sens peut manquer des fichiers nouvellement créés, comme le montre la comparaison de rsync et diff:

rsync -rcn --out-format="%n" old/ new/

donne la sortie suivante:

VERSION
doku.php
conf/mime.conf
inc/auth.php
inc/lang/no/lang.php
lib/plugins/acl/remote.php
lib/plugins/authplain/auth.php
lib/plugins/usermanager/admin.php

L'exécution de rsync dans un seul sens manque les fichiers nouvellement créés et dans l'autre sens, les fichiers supprimés sont manquants, comparez la sortie de diff:

diff -qr old/ new/

donne la sortie suivante:

Files old/VERSION and new/VERSION differ
Files old/conf/mime.conf and new/conf/mime.conf differ
Only in new/data/pages: playground
Files old/doku.php and new/doku.php differ
Files old/inc/auth.php and new/inc/auth.php differ
Files old/inc/lang/no/lang.php and new/inc/lang/no/lang.php differ
Files old/lib/plugins/acl/remote.php and new/lib/plugins/acl/remote.php differ
Files old/lib/plugins/authplain/auth.php and new/lib/plugins/authplain/auth.php differ
Files old/lib/plugins/usermanager/admin.php and new/lib/plugins/usermanager/admin.php differ

L'exécution de rsync dans les deux sens et le tri de la sortie pour supprimer les doublons révèlent que le répertoire data/pages/playground/et le fichier data/pages/playground/playground.txtont été manqués initialement:

(rsync -rcn --out-format="%n" old/ new/ && rsync -rcn --out-format="%n" new/ old/) | sort | uniq

donne la sortie suivante:

VERSION
conf/mime.conf
data/pages/playground/
data/pages/playground/playground.txt
doku.php
inc/auth.php
inc/lang/no/lang.php
lib/plugins/acl/remote.php
lib/plugins/authplain/auth.php
lib/plugins/usermanager/admin.php

rsync est exécuté avec ces arguments:

  • -r "recurse dans les répertoires",
  • -c pour comparer également des fichiers de taille identique et uniquement "sauter en fonction de la somme de contrôle, pas du temps et de la taille du mod",
  • -n "effectuer un essai sans aucune modification", et
  • --out-format="%n" à "sortie des mises à jour en utilisant le FORMAT spécifié", qui est "% n" ici pour le nom de fichier uniquement

La sortie (liste des fichiers) rsyncdans les deux sens est combinée et triée à l'aide de sort, et cette liste triée est ensuite condensée en supprimant tous les doublons avecuniq

iolsmit
la source
Ne pourriez-vous pas simplement l'exécuter à l'envers ( diff new/ old/) pour voir quels répertoires ont été supprimés?
Jacques
L'exécution diff -qr new/ old/de l'exemple ci-dessus avec les tars dokuwiki produit la même sortie que diff -qr old/ new/- c'est-à-dire que vous voyez que le répertoire est nouveau / manquant mais pas les fichiers qu'il
contient
-4
rsync -rvc --delete --size-only --dry-run source dir target dir
mayank
la source