web-dev-qa-db-fra.com

diff pour ne produire que les noms de fichiers

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

222
barfoon

Depuis la page de manuel diff:

-q Indiquez uniquement si les fichiers diffèrent, pas les détails des différences.
-r Lors de la comparaison de répertoires, comparez de manière récursive tous les sous-répertoires trouvés.

Exemple de commande:

_diff -qr dir1 dir2
_

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

_$ 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
_
337
John Kugelman

Vous pouvez également utiliser rsync

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

Si vous souhaitez obtenir une liste de fichiers qui ne figurent que dans un 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 voulez lister de manière récursive 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 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 {}
13
N D

L’approche consistant à exécuter diff -qr old/ new/ présente un inconvénient majeur: il peut manquer des fichiers dans les répertoires nouvellement créés. Par exemple. dans l'exemple ci-dessous, le fichier data/pages/playground/playground.txt ne figure pas dans la sortie de diff -qr old/ new/ alors que le répertoire data/pages/playground/ est (recherche playground.txt dans votre navigateur pour comparer rapidement). J'ai aussi posté la solution suivante sur Unix et Linux Stack Exchange , mais je vais la copier ici aussi:

Pour créer une liste de fichiers nouveaux ou modifiés par programme, la meilleure solution que je puisse trouver consiste à utiliser rsync , 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 souhaitons comparer deux versions de dokuwiki pour déterminer quels fichiers ont été modifiés et lesquels ont été 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

Exécuter rsync dans un sens peut manquer des fichiers nouvellement créés, comme le montre la comparaison entre rsync et diff:

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

Exécuter rsync uniquement dans un sens omet les fichiers nouvellement créés et inversement, omettre les fichiers supprimés, comparez le résultat 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

Lancer rsync dans les deux sens et trier 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és initialement:

(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 "recurse dans des répertoires",
  • -c pour comparer également des fichiers de taille identique et uniquement "ignorer en fonction de la somme de contrôle, pas de la taille du fichier et de la date de modification",
  • -n pour "effectuer un essai sans modification", et
  • --out-format="%n" pour "afficher les mises à jour à l'aide du format spécifié", qui correspond à "% n" pour le nom de fichier uniquement

La sortie (liste des fichiers) de rsync dans les deux sens est combinée et triée à l'aide de sort. Cette liste triée est ensuite condensée en supprimant tous les doublons avec uniq.

9
iolsmit

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

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