我有一个shell脚本,我需要检查两个文件是否包含相同的数据。我对很多文件都这样做,在我的脚本中,diff命令似乎是性能瓶颈。

歌词是这样的:

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

if ($status) then ...

是否有一种更快的方法来比较文件,也许是一个自定义算法而不是默认的diff?


当前回答

快速、安全地比较任意两个文件:

if cmp --silent -- "$FILE1" "$FILE2"; then
  echo "files contents are identical"
else
  echo "files differ"
fi

它是可读的,高效的,并且适用于任何文件名,包括“' $()”

其他回答

快速、安全地比较任意两个文件:

if cmp --silent -- "$FILE1" "$FILE2"; then
  echo "files contents are identical"
else
  echo "files differ"
fi

它是可读的,高效的,并且适用于任何文件名,包括“' $()”

用树莓派3B+做了一些测试(我使用的是覆盖文件系统,需要定期同步),我自己比较了diff -q和cmp -s;注意,这是一个来自/dev/shm内部的日志,所以磁盘访问速度不是问题:

[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

我试了几次。cmp -s在我使用的测试箱上的时间始终略短。所以如果你想使用cmp -s在两个文件之间做事情....

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"

还可以尝试使用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

cksum命令将输出文件的字节计数。参见“man cksum”。

因为我很糟糕,没有足够的声誉点,我不能把这个花絮作为评论。

但是,如果您打算使用cmp命令(并且不需要/不想太冗长),您可以只获取退出状态。根据cmp手册页:

如果FILE为'-'或缺失,则读取标准输入。退出状态为0 如果输入相同,1如果不同,2如果麻烦。

所以,你可以这样做:

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

编辑:感谢大家的评论!我在这里更新了测试语法。但是,如果您正在寻找与这个答案在可读性、风格和语法方面类似的东西,我建议您使用Vasili的答案。

我喜欢@Alex Howansky用“cmp -silent”来表示这个。但我需要积极和消极的回应,所以我使用:

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

然后,我可以在终端中运行它,或者使用ssh根据常量文件检查文件。