Existe-t-il un moyen d'effectuer une comparaison récursive de deux répertoires mais de ne comparer (à leurs emplacements respectifs) que les fichiers correspondant à un nom de fichier ou à un prédicat de type de fichier spécifique ?
Par exemple. Je voudrais faire quelque chose j'aime
diff -r dir-a dir-b -filenames *.java, ivy.xml, build.xml
… ou encore mieux :
diff -r dir-a dir-b -filetype text
Il n'est clairement pas obligatoire d'utiliser diff
comme je suppose une incantation avec find
et -exec diff
pourrait aussi faire l'affaire (je ne sais tout simplement pas comment générer les chemins de fichiers complémentaires dans ce dernier cas).
Réponse acceptée :
Shellscript differ-r
Ce shellscript peut effectuer un diff récursif de deux répertoires mais ne compare (à leurs emplacements respectifs) que les fichiers qui correspondent à un nom de fichier ou à un modèle de type de fichier spécifique.
#!/bin/bash
greenvid="\0033[32m"
resetvid="\0033[0m"
if [ $# -ne 3 ]
then
echo "Usage: compare files in two directories including subdirectories"
echo " $0 <source-dir> <target-dir> <pattern>"
echo "Example: $0 subdir-1 subdir-2 \"*.txt\""
exit
fi
cmd='for pathname do
greenvid="\0033[32m"
resetvid="\0033[0m"
echo -e "${greenvid}diff \"$pathname\" \"${pathname/'\"$1\"'/'\"$2\"'}\"${resetvid}"
diff "$pathname" "${pathname/'\"$1\"'/'\"$2\"'}"
done'
#echo "$cmd"
find "$1" -type f -name "$3" -exec bash -c "$cmd" bash {} +
Démo
Fichiers :
$ find -type f
./1/ett.txt
./1/two.doc
./1/t r e.txt
./1/sub/only-one.doc
./1/sub/hello.doc
./1/sub/hejsan.doc
./differ-r2
./differ-r1
./differ-r
./2/ett.txt
./2/two.doc
./2/t r e.txt
./2/sub/hello.doc
./2/sub/hejsan.doc
Utilisation :
$ ./differ-r
Usage: compare files in two directories including subdirectories
./differ-r <source-dir> <target-dir> <pattern>
Example: ./differ-r subdir-1 subdir-2 "*.txt"
Exécution de differ-r
:
Le diff
effectué les lignes de commande sont imprimées avec du texte vert et la sortie, lorsqu'il n'y a pas de correspondance, est imprimée avec le texte par défaut (blanc sur noir dans la capture d'écran suivante).
$ ./differ-r 1 2 "*.doc"
diff "1/two.doc" "2/two.doc"
diff "1/sub/only-one.doc" "2/sub/only-one.doc"
diff: 2/sub/only-one.doc: No such file or directory
diff "1/sub/hello.doc" "2/sub/hello.doc"
2d1
< world
diff "1/sub/hejsan.doc" "2/sub/hejsan.doc"
$ ./differ-r 1 2 "*.txt"
diff "1/ett.txt" "2/ett.txt"
2c2
< stabben
---
> farsan
diff "1/t r e.txt" "2/t r e.txt"
1c1
< t r e
---
> 3
$
$ ./differ-r 1 2 "*"
diff "1/ett.txt" "2/ett.txt"
2c2
< stabben
---
> farsan
diff "1/two.doc" "2/two.doc"
diff "1/t r e.txt" "2/t r e.txt"
1c1
< t r e
---
> 3
diff "1/sub/only-one.doc" "2/sub/only-one.doc"
diff: 2/sub/only-one.doc: No such file or directory
diff "1/sub/hello.doc" "2/sub/hello.doc"
2d1
< world
diff "1/sub/hejsan.doc" "2/sub/hejsan.doc"
$ ./differ-r 2 1 "*"
diff "2/ett.txt" "1/ett.txt"
2c2
< farsan
---
> stabben
diff "2/two.doc" "1/two.doc"
diff "2/t r e.txt" "1/t r e.txt"
1c1
< 3
---
> t r e
diff "2/sub/hello.doc" "1/sub/hello.doc"
1a2
> world
diff "2/sub/hejsan.doc" "1/sub/hejsan.doc"
rsync
avec filtre
Si vous n'avez pas besoin d'obtenir une sortie décrivant la différence, sachez seulement quels fichiers sont différents ou manquants (afin que rsync
souhaitez les copier), vous pouvez utiliser la ligne de commande suivante.
rsync --filter="+ <pattern>" --filter="+ */" --filter="- *"--filter="- */" -avcn <source directory>/ <target directory>
Démo
$ rsync --filter="+ *.doc" --filter="+ */" --filter="- *" -avcn 1/ 2
sending incremental file list
./
sub/
sub/hello.doc
sub/only-one.doc
sent 276 bytes received 35 bytes 622.00 bytes/sec
total size is 40 speedup is 0.13 (DRY RUN)
sent 360 bytes received 41 bytes 802.00 bytes/sec
total size is 61 speedup is 0.15 (DRY RUN)
[email protected] /media/multimed-2/test/test0/temp $ rsync --filter="+ *.txt" --filter="+ */" --filter="- *" -avcn 1/ 2
sending incremental file list
./
ett.txt
t r e.txt
sub/
sent 184 bytes received 29 bytes 426.00 bytes/sec
total size is 21 speedup is 0.10 (DRY RUN)
Si vous voulez une sortie propre sans commenter les lignes et sans répertoires, vous pouvez grep
la sortie comme ça,
$ pattern="*.doc"; rsync --filter="+ $pattern" --filter="+ */" --filter="- *" -avcn 1/ 2 | grep "${pattern/\*/.\*}"
sub/hello.doc
sub/only-one.doc
Shellscript rsync-diff
Cette ligne peut être transformée en commande principale d'un shellscript rsync-diff
.
#!/bin/bash
LANG=C
if [ $# -ne 3 ]
then
echo "Usage: compare files in two directories including subdirectories"
echo " $0 <source-dir> <target-dir> <pattern>"
echo "Example: $0 subdir-1 subdir-2 \"*.txt\""
exit
fi
pattern="$3"; rsync --filter="+ $pattern" --filter="+ */" --filter="- *" \
-avcn "$1"/ "$2" | grep "${pattern//\*/.\*}" | grep -v \
-e '/$' \
-e '^sending incremental file list$' \
-e '^sent.*received.*sec$' \
-e '^total size is.*speedup.*(DRY RUN)$'