Différence entre deux répertoires sous Linux

Je suis en train de trouver les fichiers dans un répertoire, mais pas dans l'autre, j'ai essayé d'utiliser cette commande:

diff -q dir1 dir2

Le problème avec la commande ci-dessus qu'il trouve à la fois les fichiers dans dir1, mais pas dans dir2 ainsi que les fichiers dans dir2, mais pas dans dir1,

Je suis en train de trouver les fichiers dans dir1, mais pas dans dir2 seulement.

Voici un petit échantillon de mes données

dir1    dir2    dir3
1.txt   1.txt   1.txt
2.txt   3.txt   3.txt
5.txt   4.txt   5.txt
6.txt   7.txt   8.txt

Une autre question dans mon esprit est Comment puis-je trouver les fichiers dans dir1 mais pas dans dir2 ou dir3 en une seule commande?

224
demandé sur codeforester 2013-05-28 12:59:22

14 réponses

diff -r dir1 dir2 | grep dir1 | awk '{print $4}' > difference1.txt

Explication:

  • diff -r dir1 dir2 affiche les fichiers sont seulement dans dir1 et ceux-là seulement dans dir2 et aussi les changements des fichiers présents dans les répertoires, le cas échéant.

  • diff -r dir1 dir2 | grep dir1 affiche les fichiers sont seulement dans dir1

  • awk pour imprimer uniquement le nom de fichier.

317
répondu asclepix 2016-04-26 12:41:41

Cela devrait faire le travail:

diff -rq dir1 dir2

Options expliquées (via diff (1) page de manuel):

  • -r - comparer récursivement tous les sous-répertoires trouvés.
  • -q - affiche uniquement si les fichiers diffèrent.
87
répondu tokhi 2017-11-27 11:00:39
comm -23 <(ls dir1 |sort) <(ls dir2|sort)

Cette commande vous donnera les fichiers qui sont dans dir1 et Pas dans dir2.

À propos du signe <( ), vous pouvez le google en tant que 'substitution de processus'.

44
répondu plhn 2015-01-04 15:56:40

Un bon moyen de faire cette comparaison est d'utiliser find avec md5sum, puis diff.

Exemple:

Utilisez find pour lister tous les fichiers du répertoire, puis calculez le hachage md5 pour chaque fichier et dirigez-le vers un fichier:

find /dir1/ -type f -exec md5sum {} \; > dir1.txt

Faites la même procédure dans un autre répertoire:

find /dir2/ -type f -exec md5sum {} \; > dir2.txt

Ensuite, comparez le résultat deux fichiers avec "diff":

diff dir1.txt dir2.txt

, Cette stratégie est très utile lorsque les deux répertoires à comparer ne sont pas dans la même machine et vous devez vous assurer que que les fichiers sont égaux dans les deux répertoires.

Une autre bonne façon de faire le travail est d'utiliser git

git diff --no-index dir1/ dir2/

Cordialement!

18
répondu Adail Junior 2017-10-07 00:49:13

Meld ( http://meldmerge.org / ) fait un excellent travail à comparer les répertoires et les fichiers à l'intérieur.

Meld comparaison des répertoires

10
répondu Catalin Hritcu 2016-09-04 17:02:51

Le plugin DirDiff de Vim est un autre outil très utile pour comparer les répertoires.

vim -c "DirDiff dir1 dir2"

, Il répertorie non seulement les fichiers qui sont différents entre les répertoires, mais aussi vous permet d'inspecter/modifier avec vimdiff les fichiers qui sont différents.

10
répondu drrossum 2017-05-08 22:49:00

Une autre approche (peut-être plus rapide pour les grands répertoires):

$ find dir1 | sed 's,^[^/]*/,,' | sort > dir1.txt && find dir2 | sed 's,^[^/]*/,,' | sort > dir2.txt
$ diff dir1.txt dir2.txt

La commande sed supprime le premier composant de répertoire grâce au post D'Erik )

5
répondu jaltek 2017-05-23 11:47:31

, C'est un peu tard, mais peut aider quelqu'un. Je ne sais pas si diff ou rsync crachent juste des noms de fichiers dans un format nu comme celui-ci. Merci à plhn pour avoir donné cette belle solution que j'ai développée ci-dessous.

Si vous voulez juste les noms de fichiers pour qu'il soit facile de simplement copier les fichiers dont vous avez besoin dans un format propre, vous pouvez utiliser la commande find.

comm -23 <(find dir1 | sed 's/dir1/\//'| sort) <(find dir2 | sed 's/dir2/\//'| sort) | sed 's/^\//dir1/'

Cela suppose que dir1 et dir2 sont tous deux dans le même dossier parent. sed supprime simplement le dossier parent afin que vous puissiez comparer les pommes avec les pommes. Le dernier sed remet juste le nom dir1.

Si vous voulez juste des fichiers:

comm -23 <(find dir1 -type f | sed 's/dir1/\//'| sort) <(find dir2 -type f | sed 's/dir2/\//'| sort) | sed 's/^\//dir1/'

De Même pour les répertoires:

comm -23 <(find dir1 -type d | sed 's/dir1/\//'| sort) <(find dir2 -type d | sed 's/dir2/\//'| sort) | sed 's/^\//dir1/'
4
répondu James 2015-08-14 13:27:50

La réponse acceptée listera également les fichiers qui existent dans les deux répertoires, mais ont un contenu différent. Pour lister uniquement les fichiers qui existent dans dir1, vous pouvez utiliser:

diff -r dir1 dir2 | grep 'Only in' | grep dir1 | awk '{print $4}' > difference1.txt

Explication:

  • diff-r dir1 dir2: comparer
  • grep 'Seulement': obtenir des lignes qui contiennent "Seulement en'
  • grep dir1: récupère les lignes qui contiennent dir
4
répondu Aris 2016-09-28 16:35:39

Insatisfait de toutes les réponses, puisque la plupart d'entre elles fonctionnent très lentement et produisent une sortie inutilement longue pour les grands répertoires, j'ai écrit mon propre script Python pour comparer deux dossiers.

Contrairement à beaucoup d'autres solutions, il ne compare pas le contenu des fichiers. En outre, il ne va pas dans les sous-répertoires qui manquent dans un autre répertoire. Donc la sortie est très concis et le script fonctionne rapidement.

#!/usr/bin/env python3

import os, sys

def compare_dirs(d1: "old directory name", d2: "new directory name"):
    def print_local(a, msg):
        print('DIR ' if a[2] else 'FILE', a[1], msg)
    # ensure validity
    for d in [d1,d2]:
        if not os.path.isdir(d):
            raise ValueError("not a directory: " + d)
    # get relative path
    l1 = [(x,os.path.join(d1,x)) for x in os.listdir(d1)]
    l2 = [(x,os.path.join(d2,x)) for x in os.listdir(d2)]
    # determine type: directory or file?
    l1 = sorted([(x,y,os.path.isdir(y)) for x,y in l1])
    l2 = sorted([(x,y,os.path.isdir(y)) for x,y in l2])
    i1 = i2 = 0
    common_dirs = []
    while i1<len(l1) and i2<len(l2):
        if l1[i1][0] == l2[i2][0]:      # same name
            if l1[i1][2] == l2[i2][2]:  # same type
                if l1[i1][2]:           # remember this folder for recursion
                    common_dirs.append((l1[i1][1], l2[i2][1]))
            else:
                print_local(l1[i1],'type changed')
            i1 += 1
            i2 += 1
        elif l1[i1][0]<l2[i2][0]:
            print_local(l1[i1],'removed')
            i1 += 1
        elif l1[i1][0]>l2[i2][0]:
            print_local(l2[i2],'added')
            i2 += 1
    while i1<len(l1):
        print_local(l1[i1],'removed')
        i1 += 1
    while i2<len(l2):
        print_local(l2[i2],'added')
        i2 += 1
    # compare subfolders recursively
    for sd1,sd2 in common_dirs:
        compare_dirs(sd1, sd2)

if __name__=="__main__":
    compare_dirs(sys.argv[1], sys.argv[2])

Exemple d'utilisation:

user@laptop:~$ python3 compare_dirs.py dir1/ dir2/
DIR  dir1/out/flavor-domino removed
DIR  dir2/out/flavor-maxim2 added
DIR  dir1/target/vendor/flavor-domino removed
DIR  dir2/target/vendor/flavor-maxim2 added
FILE dir1/tmp/.kconfig-flavor_domino removed
FILE dir2/tmp/.kconfig-flavor_maxim2 added
DIR  dir2/tools/tools/LiveSuit_For_Linux64 added

Ou si vous voulez voir uniquement les fichiers depuis le premier répertoire:

user@laptop:~$ python3 compare_dirs.py dir2/ dir1/ | grep dir1
DIR  dir1/out/flavor-domino added
DIR  dir1/target/vendor/flavor-domino added
FILE dir1/tmp/.kconfig-flavor_domino added

P.S. si vous avez besoin de comparer les tailles de fichiers et les hachages de fichiers pour des changements potentiels, j'ai publié un script mis à jour ici: https://gist.github.com/amakukha/f489cbde2afd32817f8e866cf4abe779

4
répondu Ohne Kleidung 2018-08-09 06:43:31

Une façon simplifiée de comparer 2 répertoires à L'aide de la commande DIFF

Nom du fichier Diff.1 nom de fichier.2 > nom de fichier.dat > > entrez

Ouvrir le nom de fichier.dat après la fin de l'exécution

Et vous verrez: Uniquement dans le nom de fichier.1: Nom du fichier.2 Seulement dans: directory_name: name_of_file1 Seulement dans: directory_Name: name_of_file2

0
répondu nerakk 2016-07-25 14:59:34

Kdiff3 a une belle interface de diff pour les fichiers et les répertoires.

Vérifier l'URL: http://kdiff3.sourceforge.net

Cela fonctionne sous Windows et Linux.

0
répondu ayakout 2017-11-03 09:02:52

GNU grep peut inverser la recherche avec l'option -v. Cela fait que grep signale les lignes qui ne correspondent pas. Vous pouvez ainsi supprimer les fichiers de dir2 de la liste des fichiers de dir1.

grep -v -F -x -f <(find dir2 -type f -printf '%P\n') <(find dir1 -type f -printf '%P\n')

Les options -F -x indiquent à grep d'effectuer une recherche de chaîne sur toute la ligne.

0
répondu ceving 2018-08-09 07:21:36

C'est le script bash pour imprimer des commandes pour synchroniser deux répertoires

dir1=/tmp/path_to_dir1
dir2=/tmp/path_to_dir2
diff -rq $dir1 $dir2 | sed -e "s|Only in $dir2\(.*\): \(.*\)|cp -r $dir2\1/\2 $dir1\1|" |  sed -e "s|Only in $dir1\(.*\): \(.*\)|cp -r $dir1\1/\2 $dir2\1|" 
0
répondu Ebru Yener 2018-09-07 22:27:27