325 votes

diff pour afficher uniquement les noms de fichiers

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

482voto

John Kugelman Points 108754

De la page de manuel diff :

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

Exemple de commande :

diff -qr dir1 dir2

Exemple de sortie (dépend de la locale) :

$ 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

1 votes

Merci - le diff dans CentOS 7 décrit -q comme "signaler uniquement lorsque les fichiers diffèrent", ce qui est moins clair que ce que vous avez écrit.

5 votes

Cela permet de comparer le contenu réel des fichiers, ce qui est souvent ce que l'on souhaite. Cependant, la réponse rsync donne la possibilité de ne regarder que les noms et les tailles des fichiers, et non leur contenu, ce qui est parfois souhaitable.

0 votes

Fonctionne aussi sur macOS.

46voto

boksiora Points 433

Vous pouvez également utiliser rsync

rsync -rv --size-only --dry-run /my/source/ /my/dest/ > diff.out

9 votes

--size-only manquera des fichiers de taille identique mais de contenu différent, par ex. ancienne/version.txt "29a" nouveau/version.txt "29b" . Utilisez plutôt : rsync -ric --dry-run old/ new/ où l'argument "-i" permet d'obtenir directement la liste des fichiers via rsync -ric --dry-run old/ new/ | cut -d" " -f 2

14 votes

C'est une solution idéale si vous ne recherchez que des fichiers manquants (notamment dans les partages réseau), parce que il ne compare pas les contenus. Cela m'a aidé à trouver quelques fichiers qui ont échoué lors de la migration vers un nouveau NAS.

7 votes

Veillez à inclure la barre oblique de fin pour les chemins spécifiés dans la ligne de commande de rsync. Sans cela, cela ne fonctionnera pas correctement, et rsync se contentera d'énumérer tous les noms de fichiers !

18voto

N D Points 51

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

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

Si vous voulez lister récursivement tous les fichiers et répertoires différents avec leurs chemins 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 des commandes différentes à tous les fichiers.

Par exemple, je pourrais supprimer tous les fichiers et répertoires qui se trouvent dans le répertoire 1 mais pas dans le répertoire 2 :

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

13voto

iolsmit Points 313

L'approche de la course à pied 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.txt n'est pas dans la sortie de diff -qr old/ new/ alors que le répertoire data/pages/playground/ est (recherche de terrain de jeu.txt dans votre navigateur pour comparer rapidement). J'ai également publié la solution suivante sur Unix et Linux Stack Exchange mais je vais le copier ici aussi :

Pour créer une liste de fichiers nouveaux ou modifiés de manière programmatique, la meilleure solution que j'ai trouvée est d'utiliser la méthode suivante rsync , trier et uniq :

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

Laissez-moi vous expliquer 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 tars avec wget et les extrayons dans les répertoires suivants 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 d'une manière ou d'une autre peut manquer des fichiers nouvellement créés comme le montre la comparaison de rsync et diff ici :

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

donne le résultat suivant :

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

En exécutant rsync dans un seul sens, les fichiers nouvellement créés ne sont pas pris en compte et dans l'autre sens, les fichiers supprimés ne sont pas pris en compte, comparez la sortie de diff :

diff -qr old/ new/

donne le résultat suivant :

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èle que le répertoire data/pages/playground/ et le fichier data/pages/playground/playground.txt ont été manquées au départ :

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

donne le résultat suivant :

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 pour "récurer dans les répertoires",
  • -c pour comparer également des fichiers de taille identique et seulement "sauter en fonction de la somme de contrôle, et non du temps de modulation et de la taille",
  • -n pour "effectuer un essai sans modification", et
  • --out-format="%n" pour "sortir les mises à jour en utilisant le FORMAT spécifié", qui est "%n" ici pour le nom du fichier seulement.

La sortie (liste de fichiers) de rsync dans les deux sens est combiné et trié en utilisant sort et cette liste triée est ensuite condensée en supprimant tous les doublons à l'aide de la commande uniq

0 votes

Ne pouvez-vous pas simplement l'exécuter à l'envers ( diff new/ old/ ) pour voir quels répertoires ont été supprimés ?

0 votes

Running diff -qr new/ old/ sur 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.

12voto

gerardw Points 330

Sur mon système linux, pour obtenir juste les noms de fichiers

diff -q /dir1 /dir2|cut -f2 -d' '

7 votes

Je ne mets pas de noms de fichiers avec des espaces sur mon système linux. ;)

6 votes

Je ne voulais pas vous imputer cela... ;-p Juste un indice pour quelqu'un qui le fait...

0 votes

Ne fonctionne pas pour moi. La structure de mon répertoire est la suivante audit-0.0.234/audit-data-warehouse-0.0.234/ audit-0.0.235/audit-data-warehouse-0.0.235/

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X