J'ai un script shell dans lequel je dois vérifier si deux fichiers sont identiques ou non. Je le fais pour beaucoup de fichiers, et dans mon script, la commande diff
semble être le goulot d'étranglement des performances.
Voici la ligne:
diff -q $dst $new > /dev/null
if ($status) then ...
Pourrait-il y avoir un moyen plus rapide de comparer les fichiers, peut-être un algorithme personnalisé à la place de la variable par défaut diff
?
Je crois que cmp
s'arrêtera à la différence du premier octet:
cmp --silent $old $new || echo "files are different"
J'aime @Alex Howansky ont utilisé 'cmp --silent' pour cela. Mais j'ai besoin d'une réponse à la fois positive et négative pour utiliser:
cmp --silent file1 file2 && echo '### SUCCESS: Files Are Identical! ###' || echo '### WARNING: Files Are Different! ###'
Je peux ensuite l'exécuter dans le terminal ou avec un SSH pour vérifier les fichiers par rapport à un fichier constant.
Pourquoi n'obtenez-vous pas le hachage du contenu des deux fichiers?
Essayez ce script, appelez-le par exemple script.sh et exécutez-le comme suit: script.sh fichier1.txt fichier2.txt
#!/bin/bash
file1=`md5 $1`
file2=`md5 $2`
if [ "$file1" = "$file2" ]
then
echo "Files have the same content"
else
echo "Files have NOT the same content"
fi
Pour les fichiers qui ne sont pas différents, toute méthode nécessitera d'avoir lu les deux fichiers entièrement, même si la lecture avait eu lieu dans le passé.
Il n'y a pas d'alternative. Donc, créer des hachages ou des sommes de contrôle à un moment donné nécessite de lire le fichier en entier. Les gros fichiers prennent du temps.
La récupération des métadonnées de fichier est beaucoup plus rapide que la lecture d'un fichier volumineux.
Alors, y a-t-il des métadonnées de fichier que vous pouvez utiliser pour établir que les fichiers sont différents? Taille du fichier? ou même les résultats de la commande de fichier qui ne fait que lire une petite partie du fichier?
Exemple de taille de fichier fragment de code:
ls -l $1 $2 |
awk 'NR==1{a=$5} NR==2{b=$5}
END{val=(a==b)?0 :1; exit( val) }'
[ $? -eq 0 ] && echo 'same' || echo 'different'
Si les fichiers ont la même taille, vous êtes bloqué avec des lectures de fichiers complètes.
Essayez aussi d'utiliser la commande cksum:
chk1=`cksum <file1> | awk -F" " '{print $1}'`
chk2=`cksum <file2> | awk -F" " '{print $1}'`
if [ $chk1 -eq $chk2 ]
then
echo "File is identical"
else
echo "File is not identical"
fi
La commande cksum affichera le nombre d'octets d'un fichier. Voir 'homme cksum'.
Parce que je suis nul et que je n'ai pas assez de points de réputation, je ne peux pas ajouter cette friandise en commentaire.
Toutefois, si vous souhaitez utiliser la commande cmp
(et que vous n'avez pas besoin/ne voulez pas être commenté), vous pouvez simplement saisir le statut de sortie. Par la page de manuel cmp
:
Si un fichier est "-" ou manquant, lisez l'entrée standard. Le statut de sortie est 0 si les entrées sont les mêmes, 1 si différent, 2 si problème.
Donc, vous pourriez faire quelque chose comme:
STATUS="$(cmp --silent $FILE1 $FILE2; echo $?)" # "$?" gives exit status for each comparison
if [[$STATUS -ne 0]]; then # if status isn't equal to 0, then execute code
DO A COMMAND ON $FILE1
else
DO SOMETHING ELSE
fi
En faisant des tests avec un Raspberry Pi 3B + (j'utilise un système de fichiers en superposition et dois synchroniser régulièrement), j'ai effectué une comparaison de mon propre pour diff -q et cmp -s; notez qu'il s'agit d'un journal de/dev/shm, les vitesses d'accès au disque ne sont donc pas un problème:
[root@mypi shm]# dd if=/dev/urandom of=test.file bs=1M count=100 ; time diff -q test.file test.copy && echo diff true || echo diff false ; time cmp -s test.file test.copy && echo cmp true || echo cmp false ; cp -a test.file test.copy ; time diff -q test.file test.copy && echo diff true || echo diff false; time cmp -s test.file test.copy && echo cmp true || echo cmp false
100+0 records in
100+0 records out
104857600 bytes (105 MB) copied, 6.2564 s, 16.8 MB/s
Files test.file and test.copy differ
real 0m0.008s
user 0m0.008s
sys 0m0.000s
diff false
real 0m0.009s
user 0m0.007s
sys 0m0.001s
cmp false
cp: overwrite âtest.copyâ? y
real 0m0.966s
user 0m0.447s
sys 0m0.518s
diff true
real 0m0.785s
user 0m0.211s
sys 0m0.573s
cmp true
[root@mypi shm]# pico /root/rwbscripts/utils/squish.sh
Je l'ai couru plusieurs fois. cmp -s a toujours eu des temps légèrement plus courts sur la boîte de test que j'utilisais. Donc si vous voulez utiliser cmp -s pour faire des choses entre deux fichiers ...
identical (){
echo "$1" and "$2" are the same.
echo This is a function, you can put whatever you want in here.
}
different () {
echo "$1" and "$2" are different.
echo This is a function, you can put whatever you want in here, too.
}
cmp -s "$FILEA" "$FILEB" && identical "$FILEA" "$FILEB" || different "$FILEA" "$FILEB"