GNU/Linux >> Tutoriels Linux >  >> Linux

Diff -r uniquement pour certains types de fichiers ?

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)$'

Linux
  1. Comment rediriger uniquement Stderr ?

  2. Trouver uniquement certaines chaînes (domaine) Extraire un autre fichier ?

  3. Tableau des autorisations pour les types d'utilisateurs d'un fichier/répertoire et d'un système de fichiers

  4. A quoi sert le fichier .la de libtool ?

  5. rsync ne copie que certains types de fichiers à l'aide de l'option include

Commande ls sous Linux pour lister les fichiers

Exa - Un remplacement moderne de la commande ls

Comment différencier un répertoire uniquement pour les fichiers d'un type spécifique ?

diff pour afficher uniquement les noms de fichiers

Comment tarer certains types de fichiers dans tous les sous-répertoires ?

Ce guide d'étude se trompe-t-il sur les commandes permettant de déterminer les types de fichiers ?