295 votes

Trouver les fichiers existant dans un répertoire mais pas dans l'autre

J'essaie de trouver les fichiers qui existent 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'elle trouve les deux fichiers dans dir1 mais pas en dir2 ainsi que les fichiers dans dir2 mais pas en dir1 ,

J'essaie de trouver les fichiers dans dir1 mais pas en 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 qui me préoccupe est de savoir comment je peux trouver les fichiers dans dir1 mais pas en dir2 o dir3 en une seule commande ?

13voto

drrossum Points 449

De vim DirDiff est un autre outil très utile pour comparer les répertoires.

vim -c "DirDiff dir1 dir2"

Il ne se contente pas de répertorier les fichiers qui diffèrent d'un répertoire à l'autre, mais il vous permet également d'inspecter/modifier avec vimdiff les fichiers qui sont différents.

11voto

Andriy Makukha Points 3042

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

Contrairement à de nombreuses autres solutions, il ne compare pas le contenu des fichiers. Il ne va pas non plus dans les sous-répertoires qui manquent dans un autre répertoire. Le résultat est donc 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 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 et les hachages de fichiers pour détecter d'éventuels changements, j'ai publié un script mis à jour ici : https://gist.github.com/amakukha/f489cbde2afd32817f8e866cf4abe779

6voto

jaltek Points 990

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

Les sed supprime le premier composant du répertoire grâce à l'article d'Erik )

5voto

James Points 85

C'est un peu tard, mais cela peut aider quelqu'un. Je ne suis pas sûr que diff ou rsync ne produisent que des noms de fichiers dans un format dépouillé comme celui-ci. Merci à plhn pour cette solution intéressante que j'ai développée ci-dessous.

Si vous ne voulez que les noms de fichiers afin de 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 le dossier parent afin de pouvoir comparer des pommes avec des pommes. Le dernier sed ne fait que remettre le nom de dir1.

Si vous ne voulez que des fichiers :

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

Il en va 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/'

5voto

Aris Points 1407

La réponse acceptée énumérera également les fichiers qui existent dans les deux répertoires, mais dont le contenu est 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' : obtenir les lignes qui contiennent 'Only in'
  • grep dir1 : obtenir les lignes qui contiennent dir

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