假设目录中有 x 个文件(其中 x = 大于 100),并且我想比较这些文件的差异。我怎样才能完成这个任务?我正在运行 Ubuntu 18.04 机器。为了便于讨论,假设所述目录是/home/user1/music_list/,并且该目录中的文件之一是/home/user1/music_list/jazz1.txt。
答案1
这确实取决于文件是否可能基本相同。数千次比较的呈现也完全令人困惑,除非您可以识别“参考版本”或某些渐进修改序列。
我曾经受命解决一个存在可靠性问题的推出机制问题。有 160 台服务器,拥有电力网络站点各层的 16,000 个图像文件,即 250 万个文件。
基本上,我让他们投票选出最受欢迎的版本。我让每个服务器都有自己的文件校验和,并向我发送校验和、日期、大小、名称的列表。我通过校验和进行分组和计数。任何在整个集合中 100% 一致的文件都可以。任何符合 80% 以上情况的内容都会显示那些错过更新的服务器。任何低于 20% 的内容都是删除失败,或者是恶意测试文件。在 20% 到 80% 范围内的人很少。
在我的用例中,也很容易检测到上传到不同服务器且名称或路径错误的图像文件。
这种方法可能无法解决您的问题,但它可以大大减少您需要进行详细比较的次数。
答案2
你可以试试这个脚本。
我根据首选输出添加了diff
or命令。comm
for i in /home/user1/music_list/*.txt; do
index_file="$i"
echo "$(tput setaf 1)Comparing "$i" $(tput sgr 0)"
for n in /home/user1/music_list/*.txt; do
next_file="$n"
echo "$(tput setaf 5)With "$n" $(tput sgr 0)"
#comm -3 <(sort "$index_file") <(sort "$next_file")
diff -s <(sort "$index_file") <(sort "$next_file")
shift
done
done
输出与comm
Comparing z.txt
With z1.txt
With z2.txt
1
2
With z3.txt
1
22
With z4.txt
1
222
comm
当名称相同时,将打印名称但不输出z1.txt
输出与diff
Comparing z.txt
With z1.txt
Files /dev/fd/63 and /dev/fd/62 are identical
With z2.txt
1c1
< 1
---
> 2
With z3.txt
1c1
< 1
---
> 22
With z4.txt
1c1
< 1
---
> 222
答案3
/some/dir
要(递归地)一对一比较所有常规文件,您可以执行以下操作zsh
:
function {
local fileA fileB
for fileA do
shift
for fileB do
diff -su $fileA $fileB
done
done
} /some/dir/**/*(ND.)
这里显示了统一格式与上下文的差异-u
以及文件相同时的报告-s
(非标准)。
但请注意,如果文件超过 100 个,则需要进行数千次一对一比较。
使用 GNU diff
,添加--color=always
选项diff
并将匿名函数的输出传递给less -R
可能会使该输出更容易接受。
bash
与代替相同zsh
,但假设版本 4.4 或更高版本(对于)以及和实用程序readarray -d
的 GNU 实现(或兼容)(对于它们的和扩展):find
sort
-print0
-z
(
readarray -td '' files < <(
find /some/dir/ -type f -print0 | sort -z)
set -- "${files[@]}"
for fileA do
shift
for fileB do
diff -su "$fileA" "$fileB"
done
done
)
如果存在大量重复,您可以通过首先指示哪些文件相同来减少比较次数,然后仅在每组相同文件中选择一个文件与其他组中的一个文件进行比较。
和zsh
:
typeset -A set
files=(/some/dir/**/*(ND.))
for file in $files; do
sum=$(sha1sum < $file) || continue
# store the list of files having a given checksum NUL delimited
# in an associative array
set[$sum]+=$file$'\0'
done
sums=(${(k)set})
for sum1 in $sums; do
shift 1 sums
files1=(${(0)set[$sum1]}) # split on NUL
(( $#files < 2 )) || print -r All of ${(j[, ])files1} are identical
for sum2 in $sums; do
files2=(${(0)set[$sum2]})
diff -u $files1[1] $files2[1]
done
done
(未经测试)。
答案4
假设通过通知我目录 /home/user1/music_list/ 中只有一个文件是唯一的来改进上述问题。要查找哪个是唯一的文件,请考虑这个答案并告诉我您的想法:
$diff -r --from-file=/home/user1/music_list/jazz1.txt /home/user1/music_list/
我的想法是,我可以将目录 ./jazz.txt 中的一个文件与同一目录中的所有其他文件进行比较,看看哪个文件与 jazz.txt 不同。