web-dev-qa-db-fra.com

Différence entre deux répertoires sous Linux

J'essaie de trouver les fichiers existant 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 est qu'il trouve à la fois les fichiers dans dir1 mais pas dans dir2, ainsi que les fichiers dans dir2 mais pas dans dir1

J'essaie de trouver les fichiers dans dir1 mais pas uniquement dans dir2.

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 qui me préoccupe est de savoir comment trouver les fichiers dans dir1 mais pas dans dir2 ou dir3 en une seule commande.

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

Explication:

  • diff -r dir1 dir2 indique quels fichiers sont uniquement dans dir1 et ceux uniquement dans dir2, ainsi que les modifications des fichiers présents dans les deux répertoires, le cas échéant.

  • diff -r dir1 dir2 | grep dir1 montre quels fichiers ne sont que dans dir1

  • awk pour n'imprimer que le nom de fichier.

343
asclepix

Cela devrait faire le travail:

diff -rq dir1 dir2

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

  • -r - Comparez récursivement les sous-répertoires trouvés.
  • -q - Indique uniquement si les fichiers sont différents.
102
tokhi
comm -23 <(ls dir1 |sort) <(ls dir2|sort)

Cette commande vous donnera des fichiers qui sont dans dir1 et not in dir2.

À propos du signe <( ), vous pouvez le rechercher dans Google comme "substitution de processus".

45
plhn

Un bon moyen de faire cette comparaison consiste à utiliser find avec md5sum, puis un diff.

Exemple:

Utilisez find pour répertorier 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

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

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

Comparez ensuite le résultat avec deux fichiers "diff":

diff dir1.txt dir2.txt

Cette stratégie est très utile lorsque les deux répertoires à comparer ne se trouvent pas sur le même ordinateur et que vous devez vous assurer que les fichiers sont égaux dans les deux répertoires.

Un autre bon moyen de faire le travail est d’utiliser git

git diff --no-index dir1/ dir2/

Meilleures salutations!

27
Adail Junior

Meld ( http://meldmerge.org/ ) fait un excellent travail en comparant les répertoires et les fichiers qu'il contient.

 Meld comparing directories

13
Catalin Hritcu

vim's DirDiff plugin est un autre outil très utile pour comparer des répertoires.

vim -c "DirDiff dir1 dir2"

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

10
drrossum

Insatisfait de toutes les réponses, car la plupart d'entre elles fonctionnent très lentement et produisent des résultats inutilement longs pour les grands répertoires. J'ai donc écrit mon propre script Python pour comparer deux dossiers.

Contrairement à beaucoup d'autres solutions, il ne compare pas le contenu des fichiers. De plus, il n’entre pas dans les sous-répertoires manquants dans un autre répertoire. La sortie est donc assez concise 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 du 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 fichier et les hachages de fichier pour les modifications potentielles, j'ai publié un script mis à jour ici: https://Gist.github.com/amakukha/f489cbde2afd32817f8e866cf4abe779

9
Andriy Makukha

Une autre approche (peut-être plus rapide pour les grands annuaires):

$ 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 du répertoire grâce à Erik`s post )

5
jaltek

C'est un peu tard mais peut aider quelqu'un. Vous ne savez pas si diff ou rsync crache des noms de fichiers dans un format tel que celui-ci. Merci à plhn d’avoir donné cette solution intéressante que j’ai développée ci-dessous.

Si vous voulez juste les noms de fichiers pour pouvoir copier facilement 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 se trouvent dans le même dossier parent. sed supprime simplement le dossier parent afin que vous puissiez comparer des pommes avec des pommes. Le dernier sed renvoie 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 annuaires:

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

La réponse acceptée listera également les fichiers présents dans les deux répertoires, mais ayant 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 'Only in': récupère les lignes contenant 'Only in'
  • grep dir1: obtenir les lignes qui contiennent dir
4
Aris

Ceci est le script bash pour imprimer des commandes de synchronisation de 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|" 
1
Ebru Yener

Cette réponse optimise l'une des suggestions de @ Adail-Junior en ajoutant l'option -D, ce qui est utile lorsque aucun des répertoires comparés n'est un référentiel git:

git diff -D --no-index dir1/ dir2/

Si vous utilisez -D, vous ne verrez aucune comparaison avec /dev/null: text Binary files a/whatever and /dev/null differ

1
Mike Slinn

GNU grep peut inverser la recherche avec l’option -v. Cela fait grep signaler les lignes qui ne correspondent pas. Vous pouvez ainsi supprimer les fichiers dans dir2 de la liste des fichiers dans 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
ceving

Un moyen simplifié de comparer 2 répertoires à l'aide de la commande DIFF

diff nomfichier.1 nomfichier.2> nomfichier.dat >> Entrée

ouvrez le fichier filename.dat une fois l'exécution terminée.

et vous verrez: Seulement dans nomfichier.1: nomfichier.2 Seulement dans: nom_répertoire: nom_fichier1 Seulement dans: nom_répertoire: nom_fichier2

0
nerakk

kdiff3 a une interface Nice diff pour les fichiers et les répertoires.

Cela fonctionne sous Windows, Linux et macOS.

Vous pouvez l'installer de plusieurs manières:

0
ayakout