Cel mai rapid mod de a spune dacă două fișiere sunt identice în Unix/Linux?

Am un script de shell în care am nevoie pentru a verifica dacă două fișiere sunt identice sau nu. Fac acest lucru pentru o mulțime de fișiere, și, în script-ul meu din diff comanda pare a fi piedică performanță.

Aici's linia:

diff -q $dst $new > /dev/null

if ($status) then ...

Ar putea exista un mod mai rapid de a compara fișiere, poate un algoritm personalizat în loc de implicit diff?

Comentarii la întrebare (2)
Soluția

Eu cred cmp se va opri la primul octet diferența:

cmp --silent $old $new || echo "files are different"
Comentarii (10)

Îmi place @Alex Howansky au folosit 'cmp-tăcut' pentru acest lucru. Dar am nevoie de atât pozitive, cât și negative răspuns, așa că am folosi:

cmp --silent file1 file2 && echo '### SUCCESS: Files Are Identical! ###' || echo '### WARNING: Files Are Different! ###'

Atunci eu pot rula acest lucru în terminal sau cu un ssh pentru a verifica fișierele împotriva unei constante de fișier.

Comentarii (2)

De ce nu't ai hash de fișiere de conținut?

Încercați acest script, spunem, de exemplu script.sh și apoi rulați-l, după cum urmează: script.sh file1.txt file2.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
Comentarii (23)

Pentru fișierele care nu sunt diferite, orice metoda vei avea nevoie să fi citit ambele fișiere în întregime, chiar dacă a fost citit în trecut.

Nu există nici o alternativă. Deci, crearea de hash-uri sau sume de control la un moment dat în timp, necesită citirea întregului fișier. Fișiere mari ia timp.

Fișierul de metadate recuperarea este mult mai rapidă decât citirea unui fișier mare.

Deci, este acolo orice fișier de metadate, puteți utiliza pentru a stabili că fișierele sunt diferite? Dimensiune ? sau chiar rezultatele din fișierul de comandă care nu citi doar o mică parte din fișier?

Dimensiune exemplu fragment de cod:

  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'  

Dacă fișierele sunt de aceeași mărime, apoi te-ai pricopsit cu dosar complet citește.

Comentarii (1)

De asemenea, încercați să utilizați cksum comanda:

chk1=`cksum  | awk -F" " '{print $1}'`
chk2=`cksum  | awk -F" " '{print $1}'`

if [ $chk1 -eq $chk2 ]
then
  echo "File is identical"
else
  echo "File is not identical"
fi

La cksum comandă va afișa numărul de octet din fișier. A se vedea 'om cksum'.

Comentarii (1)

Pentru că nu mă pricep și nu't au suficient de puncte de reputație nu pot't adăugați această informație într-un comentariu.

Dar, dacă aveți de gând să utilizați cmp comandă (și nu't nevoie/doresc să fie verbose) puteți apuca doar starea de iesire. Pecmp` om pagină:

Dacă un FIȘIER este '-' sau lipsește, citit de la intrarea standard. Starea de ieșire este 0 dacă intrările sunt la fel, 1 dacă este diferită, 2 dacă probleme.

Deci, ai putea face ceva de genul:

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
Comentarii (0)

Fac niste teste cu un Raspberry Pi 3B+ (I'm, folosind o suprapunere sistemul de fișiere, și aveți nevoie pentru a sincroniza periodic), am făcut o comparație pentru diff-q și cmp -s; rețineți că acest lucru este un jurnal din interiorul /dev/shm, astfel încât accesul la disc vitezele sunt o non-problema:

[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

Am alergat-o de câteva ori. cmp -s avea în mod constant ușor mai scurte ori pe cutia de testare am folosit. Deci, dacă doriți să utilizați cmp -s pentru a face lucrurile între două fișiere....

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"
Comentarii (0)