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

歌词是这样的:

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

if ($status) then ...

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


当前回答

对于没有不同的文件,任何方法都需要完全读取两个文件,即使读取是在过去。

除此之外别无选择。因此,在某个时间点上创建哈希或校验和需要读取整个文件。大文件需要时间。

文件元数据检索比读取大文件快得多。

那么,您是否可以使用任何文件元数据来确定这些文件是不同的? 文件大小?或者甚至文件命令只读取文件的一小部分的结果?

文件大小示例代码片段:

  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'  

如果文件大小相同,则只能读取完整的文件。

其他回答

我相信cmp将在第一个字节差处停止:

cmp --silent $old $new || echo "files are different"

对于没有不同的文件,任何方法都需要完全读取两个文件,即使读取是在过去。

除此之外别无选择。因此,在某个时间点上创建哈希或校验和需要读取整个文件。大文件需要时间。

文件元数据检索比读取大文件快得多。

那么,您是否可以使用任何文件元数据来确定这些文件是不同的? 文件大小?或者甚至文件命令只读取文件的一小部分的结果?

文件大小示例代码片段:

  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'  

如果文件大小相同,则只能读取完整的文件。

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

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"

如果您正在寻找更多可自定义的diff,那么可以使用git diff。

if (git diff --no-index --quiet -- old.txt new.txt) then
  echo "files contents are identical"
else
  echo "files differ"
fi

——安静 禁用程序的所有输出。意味着—退出代码。

—退出代码 使用类似diff(1)的代码退出程序。也就是说,如果有差异,它以1退出,0表示没有差异。


此外,还有各种算法和设置可供选择:

——diff-algorithm ={耐心| |最小直方图|迈尔斯} 选择一个差分算法。其变体如下: 基本的贪婪差分算法。目前,这是 违约。 花额外的时间来确保尽可能小的差异 生产。 在生成补丁时使用“patience diff”算法。 该算法将耐心算法扩展到“支持” 低发生率的公共元素”。