我有一个shell脚本,需要检查两个文件是否包含相同的数据。我要对很多文件进行这样的检查,在我的脚本中,diff
命令似乎是性能瓶颈。
以下是该行代码:
diff -q $dst $new > /dev/null
if ($status) then ...
有没有更快的比较文件的方法,也许是使用自定义算法而不是默认的 diff
?
cmp
会在第一个字节的差异处停止。cmp --silent $old $new || echo "files are different"
cmp -s $old $new
也可以使用。 -s
是 --silent
的缩写。 - tim-phillipscmp
实现都会首先检查文件大小。这是 GNU 版本的实现,如果您想查看它包含的其他优化,请访问以下链接:http://git.savannah.gnu.org/cgit/diffutils.git/tree/src/cmp.c - Ryan Graham我像@Alex Howansky一样使用了'cmp --silent'。但是我需要正面和负面的响应,所以我使用:
cmp --silent file1 file2 && echo '### SUCCESS: Files Are Identical! ###' || echo '### WARNING: Files Are Different! ###'
我可以在终端或通过ssh运行此命令,以检查文件是否与一个不变的文件相同。
echo success
命令(或者替代它的其他命令)失败了,你的 "negative response" 命令将会被执行。你应该使用一个 "if-then-else-fi" 结构体。例如,像 这个简单的例子。 - Wildcard快速而安全地比较任意两个文件:
if cmp --silent -- "$FILE1" "$FILE2"; then
echo "files contents are identical"
else
echo "files differ"
fi
它易读、高效,并适用于任何文件名,包括"` $()
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的答案。
cmp --silent $FILE1 $FILE2 ; if [ "$?" == "1" ]; then echo "files differ"; fi
,而这又是一种更复杂的做法cmp --silent $FILE1 $FILE2 || echo "files differ"
,因为您可以直接在表达式中使用命令。它代替了$?
。因此,将比较命令的存在状态。这就是其他答案所做的。顺便说一下,如果有人遇到了“-silent”,则不是所有地方都支持它(忙碌盒)。使用“-s”。 - papoif cmp --silent -- "$FILE1" "$FILE2"; then ... else ... fi
。 - VasiliNovikovif command; then ... else ... fi
此外,@Gregory您的代码存在常见的bash陷阱。 [[
实际上是bash语法,应该按照以下方式进行:if [[ ... ]]
(注意空格)一个非常好的URL,可了解常见的bash陷阱:https://mywiki.wooledge.org/BashPitfalls - Chevrautsha256sum oldFile > oldFile.sha256
echo "$(cat oldFile.sha256) newFile" | sha256sum --check
newFile: OK
newFile: FAILED
sha256sum: WARNING: 1 computed checksum did NOT match
echo "$(sha256sum "$1" | sed 's/ .*//') $2" | sha256sum --check 1>/dev/null
。 - undefined 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'
如果文件大小相同,则只能进行完整文件读取。
ls -n
命令来避免用户或组名中有空格的问题。 - tricasse也尝试使用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'。
md5
无论如何都会读取整个文件,所以 cmp
在找到第一个不同点后停止,速度会更快。 - Francesco Dondi[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
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"
same-contents() {
echo "$(sha256sum "$1" | sed 's/ .*//') $2" | sha256sum --check 1>/dev/null 2>&1
}
alias same-file="same-contents" # Technically the same "file" has the same inode
if same-contents file1.txt file2.txt; then
echo true
else
echo false
fi
sed
命令会去掉文件名,只留下哈希值。cmp
,因为它专为此而设计,可以逐字节比较,而哈希需要读取整个文件,但我觉得这是一个有趣的脚本。git diff
。if (git diff --no-index --quiet old.txt new.txt) then
echo "files contents are identical"
else
echo "files differ"
fi
diff
和cmp
之间有任何显着差异。 - wedi