Est-il possible de comparer deux répertoires avec rsync et d'imprimer uniquement les différences? Il y a une option de dry-run, mais quand j'augmente la verbosité à un certain niveau, chaque fichier comparé est affiché.
ls -alR
et diff
n'est pas une option ici, car il y a des liens physiques dans la source qui rendent chaque ligne différente. (Bien sûr, je pourrais supprimer cette colonne avec Perl.)
Vous devrez probablement exécuter quelque chose comme rsync -avun --delete
dans les deux sens.
Mais qu'essayez-vous réellement d'accomplir?
Mise à jour:
rsync -avun --delete $TARGET $SOURCE |grep "^deleting "
vous donnera une liste de fichiers qui n'existent pas dans le répertoire cible.
"grep delet" car chaque ligne affiche: delet ing ..file ..
rsync -avun $SOURCE $TARGET
vous donnera une liste de fichiers "différents" (y compris les nouveaux fichiers).
Pour ajouter à la réponse de Nils (pour toute personne rencontrant cela via Google), par défaut rsync
compare uniquement les tailles de fichier et les temps de modification pour savoir s'il y a des différences. (Si ceux-ci sont différents, cela en fait plus, mais s'ils sont identiques, cela s'arrête là.)
Si vous souhaitez comparer le fichier réel conten, même pour les fichiers qui ont la même taille et la dernière heure de modification, ajoutez l'indicateur -c
pour dire à rsync
de comparer les fichiers à l'aide d'une somme de contrôle.
rsync -avnc $SOURCE $TARGET
(Le -u
L'option indique à rsync d'ignorer les fichiers plus récents dans $TARGET
que sur $SOURCE
, ce que vous ne voulez probablement pas si vous comparez le contenu.)
Pour ceux qui connaissent moins rsync
:
rsync -rvnc --delete ${SOURCE}/ ${DEST}
-n
: bit le plus important - faire pas changer quoi que ce soit;-rc
: compare uniquement le contenu (sinon utilisez -ac
);-v
: liste les fichiers)--delete
: recherchez une différence symétrique et non unidirectionnelle./
signifie "regardez à l'intérieur du répertoire et comparez son conten à la destination".Il imprimera une sortie
rsync
habituelle,
- avec un <nomfichier> sur une ligne pour chaque "nouveau" fichier dans
${SOURCE}
et une "suppression de <nomfichier>" ligne pour chaque "nouveau" fichier dans
${DEST}
.Il peut également afficher quelques avertissements, comme "ignorer les fichiers non réguliers <nomfichier>" pour les liens symboliques.
PS. Je sais que c'est un terrible PS - mais il a en effet été ajouté dans Rush. Néanmoins, je parie que l'on peut trouver cela utile.
find $SOURCE -type f -exec md5sum {} \; | tee source.md5
find $DEST -type f -exec md5sum {} \; | tee dest.md5
Si les noms de fichiers ne contiennent pas de sauts de ligne, nous pouvons alors trier les deux *.md5
fichiers et diff
eux. (Cela ne fonctionnera cependant que pour les fichiers; c'est-à-dire qu'un répertoire vide de chaque côté ne sera pas détecté.)
Étonnamment aucune réponse en 6 ans utilise le -i
option ou donne une sortie Nice alors je vais y aller:
rsync -rin --ignore-existing "$LEFT_DIR"/ "$RIGHT_DIR"/|sed -e 's/^[^ ]* /L /'
rsync -rin --ignore-existing "$RIGHT_DIR"/ "$LEFT_DIR"/|sed -e 's/^[^ ]* /R /'
rsync -rin --existing "$LEFT_DIR"/ "$RIGHT_DIR"/|sed -e 's/^/X /'
Voici un exemple de sortie:
L file-only-in-Left-dir
R file-only-in-right-dir
X >f.st...... file-with-dif-size-and-time
X .f...p..... file-with-dif-perms
Notez le premier caractère de chaque ligne:
L
/R
signifie que le fichier/dir apparaît uniquement dans le L
eft ou R
ight dir.X
signifie que le fichier apparaît des deux côtés mais n'est pas le même (auquel cas les 11 caractères suivants vous donnent plus d'informations. s
, t
et p
illustrent les différences entre s ize, t ime et p ermissions respectivement - pour plus d'informations, essayez man rsync
et recherchez --itemize-changes
).Si vous souhaitez également comparer le propriétaire/groupe/autorisations des fichiers, ajoutez les options -o
/-g
/-p
respectivement. Enfin, notez que par défaut, rsync considère deux fichiers comme identiques s'ils ont le même nom, la même heure et la même taille. C'est extrêmement rapide et la plupart du temps plus que suffisant, mais si vous voulez être sûr à 100%, ajoutez -c
pour comparer également le contenu des fichiers avec le même nom, la même heure et la même taille.
C'est ici. Appelez ça comme ça
diff-dirs Left_Dir Right_Dir [options]
Toutes les options mentionnées ci-dessus dans la section "Options supplémentaires que vous souhaitez utiliser" s'appliquent également ici.
#!/bin/bash
# Compare two directories using rsync and print the differences
# CAUTION: options MUST appear after the directories
#
# SYNTAX
#---------
# diff-dirs Left_Dir Right_Dir [options]
#
# EXAMPLE OF OUTPUT
#------------------
# L file-only-in-Left-dir
# R file-only-in-right-dir
# X >f.st...... file-with-dif-size-and-time
# X .f...p..... file-with-dif-perms
#
# L / R mean that the file/dir appears only at the `L`eft or `R`ight dir.
#
# X means that a file appears on both sides but is not the same (in which
# case the next 11 characters give you more info. In most cases knowing
# that s,t,T and p depict differences in Size, Time and Permissions
# is enough but `man rsync` has more info
# (look at the --itemize-changes option)
#
# OPTIONS
#---------
# All options are passed to rsync. Here are the most useful for the purpose
# of directory comparisons:
#
# -c will force comparison of file contents (otherwise only
# time & size is compared which is much faster)
#
# -p/-o/-g will force comparison of permissions/owner/group
if [[ -z $2 ]] ; then
echo "USAGE: $0 dir1 dir2 [optional rsync arguments]"
exit 1
fi
set -e
LEFT_DIR=$1; shift
RIGHT_DIR=$1; shift
OPTIONS="$*"
# Files that don't exist in Right_Dir
rsync $OPTIONS -rin --ignore-existing "$LEFT_DIR"/ "$RIGHT_DIR"/|sed -e 's/^[^ ]* /L /'
# Files that don't exist in Left_Dir
rsync $OPTIONS -rin --ignore-existing "$RIGHT_DIR"/ "$LEFT_DIR"/|sed -e 's/^[^ ]* /R /'
# Files that exist in both dirs but have differences
rsync $OPTIONS -rin --existing "$LEFT_DIR"/ "$RIGHT_DIR"/|sed -e 's/^/X /'
Nous appelons rsync comme ceci:
rsync -rin ...
Nous utilisons -i
(--itemize-changes
) pour indiquer à rsync d'imprimer une ligne de sortie pour chaque fichier contenant des informations sur les différences entre les deux répertoires. Nous avons besoin -n
pour supprimer le comportement normal de rsync (qui consiste à essayer de synchroniser les deux répertoires en copiant/supprimant des fichiers). nous avons aussi besoin de -r
pour fonctionner récursivement pour tous les fichiers/sous-répertoires.
Nous appelons rsync trois fois:
1er appel: imprimer des fichiers qui n'existent pas dans Dir_B. Nous devons utiliser --ignore-existing
pour ignorer les fichiers qui existent des deux côtés.
rsync -rin --ignore-existing $DIR_A/ $DIR_B/
2ème appel: exactement comme avant mais nous échangeons l'ordre de DIR_A/DIR_B.
e appel: Enfin, nous utilisons --existing
pour vérifier uniquement les fichiers qui apparaissent dans les deux répertoires.
rsync -rin --existing $DIR_A/ $DIR_B/
Je comprends de votre question que vous ne voulez pas utiliser diff sur ls, mais vous pouvez également utiliser diff récursivement sur les répertoires:
diff -rq DIR1 DIR2
Il m'a fallu quelques essais pour que cela fonctionne. La réponse de Nils requiert que $TARGET
Se termine par un /
Final, comme expliqué par ジ ョ ー ジ.
Voici une version qui ajoute explicitement le /
De fin:
rsync -avun --delete ${TARGET}/ ${SOURCE} | sed -ne 's/^deleting *//p'
Cela donne la liste des fichiers qui existent sous le répertoire ${SOURCE}
Mais pas sous le répertoire ${TARGET}
.
J'utilise sed
ici pour supprimer le premier deleting
des lignes de sortie et pour imprimer uniquement ces lignes.
Je n'utilise pas l'option rsync
-c
Car la comparaison du contenu des fichiers serait beaucoup plus lente pour mes cas d'utilisation, et la comparaison des tailles de fichiers et des temps de modification semble également suffisante dans ces cas. Je n'ai aucune raison de soupçonner que mes ordinateurs souffrent de problèmes d'horloge ou que quelque chose a changé de manière malveillante les horodatages. En outre, le résultat de -c
Ne peut pas modifier la décision de supprimer un fichier, uniquement la décision de mettre à jour ou de conserver un fichier.
J'utilise également -u
Et -a
(Plutôt que -r
), Afin de pouvoir réutiliser ultérieurement la ligne de commande et la modifier pour copier les répertoires et fichiers sélectionnés de ${SOURCE}
À ${TARGET}
, Comme ceci:
rsync -avu ${SOURCE}/{dirA,dirB,fileX} ${TARGET} # copy some files
J'ai une autre idée de faire ça:
rsync -rn --out-format=FILEDETAIL::%n $TARGET $SOURCE | grep "^FILEDETAIL"
Vous pouvez faire correspondre "FILEDETAIL ::" avec la sortie de la commande. Vous pouvez également modifier la chaîne "FILEDETAIL ::". "% N" est le nom du fichier.
Comme indiqué dans rsync
manpage :
-r, --recursive recurse into directories -n, --dry-run perform a trial run with no changes made