如何只检测我的 bash shell 脚本中的不同文件?
How to detect only the different files in my bash shell script?
我正在尝试比较两个存储库中的文件列表,以尝试标记哪些文件已更改。问题是,我的代码说它们都是不同的。但是检查每个哈希摘要显示许多摘要是相同的。
while IFS= read -r filename;
do
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# inspecting the digest of each file individually #
# shows many files are identical and so are the digests #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
md5 old/$filename; # a456cca87913a4788d980ba4c2f254be
md5 new/$filename; # a456cca87913a4788d980ba4c2f254be
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# the below conditional is only supposed to echo "differs" #
# if the two digests are different #
# but, instead, it echoes "differs" on every file comparison #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[[ $(md5 old/$filename) = $(md5 new/$filename) ]] || echo differs; # differs
done < files-to-compare.txt
如何修复此错误并仅获取报告不同的文件?
编辑
此外,请注意使用 ==
而不是 =
,如
$(md5 old/$filename) == $(md5 new/$filename) ]] || echo differs;
产生完全相同的错误输出。
编辑2
一条评论建议使用引号。那也不行。
"$(md5 old/$filename)" == "$(md5 new/$filename)" ]] || echo differs;
要仅查看两个文件的差异,您可以使用 grep,它只会打印不同的行。
grep -v -F -x -f filename1 filename2
comm 也可用于此目的,仅打印两个文件之间的差异。
comm -13 <(sort filename1) <(sort filename2)
您可以使用 diff
命令来比较文件内容,而不是计算 MD5 校验和。它的主要用途是逐行处理文件并比较它们的差异(并生成补丁),但它也可以很容易地用于此目的。如果两个文件之间没有差异,returns 退出 0
,如果有任何差异,则 1
退出。
while IFS= read -r filename;
do
if ! diff "old/$filename" "new/$filename" > /dev/null;
then
echo "“$filename” differs"
fi
done < files-to-compare.txt
如果您使用的是 GNU diff
,您可以简单地使用其 -q, --brief
选项,该选项仅报告文件不同(而不是详细说明它们的不同之处):
while IFS= read -r filename;
do
diff -q "old/$filename" "new/$filename"
done < files-to-compare.txt
这是您更正的脚本:
while IFS= read -r filename;
do
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# inspecting the digest of each file individually #
# shows many files are identical and so are the digests #
# It also prints MD5 (full file path) = md5_signature! #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
md5 "old/$filename" # please use double quotes
md5 "new/$filename"
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Using -q eliminates all output from md5 except the sig #
# Your script now works correctly #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[[ $(md5 -q "old/$filename") == $(md5 -q "new/$filename") ]] || echo differs; # differs
done < files.txt
问题:
- 您打错了
new/$fullfile
而不是 new/$filename
- 您应该在文件扩展名周围使用
"new/$filename"
(即使用双引号)
- 使用
md5 -q
比较md5
在不同文件上的输出。否则 md5
,默认情况下,以 MD5 (full_path/base_name) = 2504fcc0c0a57d14aa6b4193b5efaf94
的形式打印输入文件路径。由于这些路径在两个不同的目录中保证是不同的,不同的路径名会导致字符串比较失败。
以上评论假定您在 BSD 上使用 md5
,或者很可能在 macOS 上使用。
这是一个替代解决方案,它既适用于 Linux 和 md5sum
,也适用于 BSD 和 md5
。只需将文件的内容提供给任一程序的标准输入,只打印 md5 签名:
$ md5 <new/file.pdf
2504fcc0c0a57d14aa6b4193b5efaf94
vs 如果使用文件名,则打印路径并打印使用的 MD5 哈希签名:
$ md5 new/file.pdf
MD5 (new/file.pdf) = 2504fcc0c0a57d14aa6b4193b5efaf94
Linux 或 GNU 核心实用程序上的 md5sum
也是如此。
在我的 Linux ubuntu 上,有 md5sum
命令:它打印摘要和文件名:
md5sum myFile
215e0f7b4ea9fd9ea5f31106155839fe myFile
我的意思是你只需要从输出中提取摘要:
md5sum myFile | sed 's/^\([^[:blank:]]*\).*$//g'
215e0f7b4ea9fd9ea5f31106155839fe
然后在测试中使用最后一个命令行:
...
[[ $(md5sum old/"${filename}" | sed 's/^\([^[:blank:]]*\).*$//g') = $(md5sum new/"${filename}" | sed 's/^\([^[:blank:]]*\).*$//g') ]] || echo differs;
...
我正在尝试比较两个存储库中的文件列表,以尝试标记哪些文件已更改。问题是,我的代码说它们都是不同的。但是检查每个哈希摘要显示许多摘要是相同的。
while IFS= read -r filename;
do
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# inspecting the digest of each file individually #
# shows many files are identical and so are the digests #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
md5 old/$filename; # a456cca87913a4788d980ba4c2f254be
md5 new/$filename; # a456cca87913a4788d980ba4c2f254be
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# the below conditional is only supposed to echo "differs" #
# if the two digests are different #
# but, instead, it echoes "differs" on every file comparison #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[[ $(md5 old/$filename) = $(md5 new/$filename) ]] || echo differs; # differs
done < files-to-compare.txt
如何修复此错误并仅获取报告不同的文件?
编辑
此外,请注意使用 ==
而不是 =
,如
$(md5 old/$filename) == $(md5 new/$filename) ]] || echo differs;
产生完全相同的错误输出。
编辑2
一条评论建议使用引号。那也不行。
"$(md5 old/$filename)" == "$(md5 new/$filename)" ]] || echo differs;
要仅查看两个文件的差异,您可以使用 grep,它只会打印不同的行。
grep -v -F -x -f filename1 filename2
comm 也可用于此目的,仅打印两个文件之间的差异。
comm -13 <(sort filename1) <(sort filename2)
您可以使用 diff
命令来比较文件内容,而不是计算 MD5 校验和。它的主要用途是逐行处理文件并比较它们的差异(并生成补丁),但它也可以很容易地用于此目的。如果两个文件之间没有差异,returns 退出 0
,如果有任何差异,则 1
退出。
while IFS= read -r filename;
do
if ! diff "old/$filename" "new/$filename" > /dev/null;
then
echo "“$filename” differs"
fi
done < files-to-compare.txt
如果您使用的是 GNU diff
,您可以简单地使用其 -q, --brief
选项,该选项仅报告文件不同(而不是详细说明它们的不同之处):
while IFS= read -r filename;
do
diff -q "old/$filename" "new/$filename"
done < files-to-compare.txt
这是您更正的脚本:
while IFS= read -r filename;
do
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# inspecting the digest of each file individually #
# shows many files are identical and so are the digests #
# It also prints MD5 (full file path) = md5_signature! #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
md5 "old/$filename" # please use double quotes
md5 "new/$filename"
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Using -q eliminates all output from md5 except the sig #
# Your script now works correctly #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[[ $(md5 -q "old/$filename") == $(md5 -q "new/$filename") ]] || echo differs; # differs
done < files.txt
问题:
- 您打错了
new/$fullfile
而不是new/$filename
- 您应该在文件扩展名周围使用
"new/$filename"
(即使用双引号) - 使用
md5 -q
比较md5
在不同文件上的输出。否则md5
,默认情况下,以MD5 (full_path/base_name) = 2504fcc0c0a57d14aa6b4193b5efaf94
的形式打印输入文件路径。由于这些路径在两个不同的目录中保证是不同的,不同的路径名会导致字符串比较失败。
以上评论假定您在 BSD 上使用 md5
,或者很可能在 macOS 上使用。
这是一个替代解决方案,它既适用于 Linux 和 md5sum
,也适用于 BSD 和 md5
。只需将文件的内容提供给任一程序的标准输入,只打印 md5 签名:
$ md5 <new/file.pdf
2504fcc0c0a57d14aa6b4193b5efaf94
vs 如果使用文件名,则打印路径并打印使用的 MD5 哈希签名:
$ md5 new/file.pdf
MD5 (new/file.pdf) = 2504fcc0c0a57d14aa6b4193b5efaf94
Linux 或 GNU 核心实用程序上的 md5sum
也是如此。
在我的 Linux ubuntu 上,有 md5sum
命令:它打印摘要和文件名:
md5sum myFile
215e0f7b4ea9fd9ea5f31106155839fe myFile
我的意思是你只需要从输出中提取摘要:
md5sum myFile | sed 's/^\([^[:blank:]]*\).*$//g'
215e0f7b4ea9fd9ea5f31106155839fe
然后在测试中使用最后一个命令行:
...
[[ $(md5sum old/"${filename}" | sed 's/^\([^[:blank:]]*\).*$//g') = $(md5sum new/"${filename}" | sed 's/^\([^[:blank:]]*\).*$//g') ]] || echo differs;
...