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.
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.
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.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".
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!
Meld ( http://meldmerge.org/ ) fait un excellent travail en comparant les répertoires et les fichiers qu'il contient.
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.
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
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 )
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/'
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:
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|"
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
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.
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