Diff plusieurs fichiers, vrai si tous ne sont pas égaux

18

J'ai un certain nombre de fichiers, je veux vérifier que tous ces fichiers ont le même contenu.

Quelle ligne de commande pourrais-je utiliser pour vérifier cela?

L'utilisation pourrait être quelque chose comme:

$ diffseveral file1 file2 file3 file4

Résultat:

All files equals

OU

Files are not all equals
Nicolas Raoul
la source

Réponses:

27

Avec GNU diff, passez un des fichiers en argument --from-fileet n'importe quel nombre en opérande:

$ diff -q --from-file file1 file2 file3 file4; echo $?
0
$ echo >>file3
$ diff -q --from-file file1 file2 file3 file4; echo $?
Files file1 and file3 differ
1
Gilles 'SO- arrête d'être méchant'
la source
4

Que diriez-vous:

md5sum * | awk 'BEGIN{rc=1}NR>1&&$1!=last{rc=0}{last=$1}END{exit rc}'

Calcule la valeur MD5 pour chaque fichier, puis compare chaque entrée avec la suivante, le cas échéant, puis retourne un état de sortie nul (vrai). Ce serait beaucoup plus court s'il retournait faux s'il était différent:

md5sum * | awk 'NR>1&&$1!=last{exit 1}{last=$1}'

Il n'est pas nécessaire de trier car nous vérifions simplement s'il en existe d'autres.

Arcege
la source
1
Dans la version plus courte, je suppose que $ 1 devrait être utilisé, car $ 0 contient un nom de fichier unique.
xanpeng
2

Le code suivant doit être assez explicite. $#est le nombre d'arguments de fichier, et les shiftconsomme juste un à la fois. Utilise cmp -spour une comparaison silencieuse octet.

#!/bin/sh
# diffseveral

if [ $# -lt 2 ]; then
    printf '%s\n' "Usage: $0 file1 file2 [files ...]" >&2
    exit 2
fi

oldfile="$1"
shift

while [ $# -gt 0 ]; do
    newfile="$1"
    if ! cmp -s "$oldfile" "$newfile"; then
         echo 'Files differ.'
         exit 1;
    fi

    shift
done

echo 'All files identical.'
exit 0
jw013
la source
0

Vous ne pouvez que diffdeux à la fois, mais il est assez facile de vérifier s'ils sont tous égaux:

if diff file1 file2 && diff file2 file3 && diff file3 file4; then
    echo All equal
else
    echo Not
fi

Si vous en avez assez pour justifier une boucle, utilisez quelque chose comme ceci:

alleq () {  
    for file; do 
        diff -q "$1" "$file" >/dev/null || return 1
    done
}

if alleq file1 file2 ...; then
    echo All equal
else 
    echo Not
fi
Kevin
la source
Maladroit si vous avez cinquante fichiers, ou si vous ne savez pas combien
DarenW
1
@ DarenW Bien sûr, si vous en avez autant, utilisez simplement une boucle.
Kevin