我有两个目录A和B;每一个都包含很多子目录
geom001, geom002 ....etc
每个子目录都包含一个名为 results.txt 的文件。我想在不打开其中任何一个的情况下比较 A 中的每个文件与 B 中的每个文件,并查找 A 中是否有一个或多个文件与 B 中的一个或多个文件类似。我如何在 a 中使用如下命令循环搜索所有文件?
cmp --silent file1 file2 || echo "file1 and file2 are different"
答案1
如果文件完全相同,那么它们的md5sum
s 将完全相同,因此您可以使用:
find A/ B/ -type f -exec md5sum {} + | sort | uniq -w32 -D
md5sum 的长度始终为 128 位(或 16 个字节或 32 个十六进制数字),并且md5sum
程序输出使用十六进制数字。因此,我们使用命令-w32
上的选项uniq
来仅比较每行的前 32 个字符。
这将打印全部具有非唯一 md5sum 的文件。即重复。
注意:这将检测重复文件,无论它们位于 A/ 或 B/ 中的哪个位置 - 因此如果/A/subdir1/file
和A/subdir2/otherfile
相同,它们仍然会被打印。如果有多个重复项,则将全部打印出来。
您可以通过管道将 md5sums 从输出中删除,例如,awk '{print $2}'
或与cut
或等。我将它们留在输出中,因为它们是或等sed
中的关联数组(又名“哈希”)的有用键,以便进一步使用加工。awk
perl
答案2
我想这会让你更接近。它将列出 A 中所有名为 results 的文件与 B 中名为 results 的所有文件的 cmp 输出。
find ./A -name results | xargs -I REPLACESTR find ./B -name results -exec cmp REPLACESTR {} \;
答案3
问题/请求的表面挑战可能是递归方面。
假设这是一个足够的实用程序,并且要比较的cmp
文件夹/目录具有相同的结构(即相同的文件和文件夹)并且驻留在相同的根路径中 - 您可以尝试类似的操作:1
2
#!/bin/bash
ROOT=$PWD ; # #// change to absolute path eg: /home/aphorise/my_files
PWD1="1/*" ;
PWD2="2/*" ;
# #// Get lengths of seperators
IFS=/ read -a DP <<< ${ROOT} ;
PLEN1=${#DP[*]} ;
IFS=/ read -a DP <<< ${PWD1} ;
PLEN1=$(echo "${#DP[*]}" + $PLEN1 - 1 | bc) ;
IFS=/ read -a DP <<< ${PWD2} ;
PLEN2=${#DP[*]} ;
# #// Set absolute paths:
PWD1="${ROOT}/${PWD1}" ;
PWD2="${ROOT}/${PWD2}" ;
DIFFS=0 ;
function RECURSE()
{
for A_FILE in $1 ; do
if [ -d $A_FILE ] ; then
RECURSE "$A_FILE/*" ;
else
IFS=/ read -a FP <<< ${A_FILE} ;
B_FILE="${PWD2:0:${#PWD2}-${#PLEN2}}$( IFS=/ ; printf "%s" "${FP[*]:$PLEN1:512}"; )" ;
if ! cmp ${A_FILE} ${B_FILE} 1>/dev/null ; then printf "$A_FILE --> $B_FILE <-- DIFFER.\n" ; ((++DIFFS)) ; fi ;
fi ;
done ;
}
printf "Starting comparison on $PWD1 @ $(date)\n\n" ;
RECURSE "${PWD1[*]}" ;
if ((DIFFS != 0)) ; then printf "\n= $DIFFS <= differences detected.\n" ; fi ;
printf "\nCompleted comparison @ $(date)\n" ;
更新:
接下来是另一个脚本 - 在收到额外反馈之后 - 无条件地将目录中的所有文件1
与2
:
#!/bin/bash
PWD1="$PWD/1/*" ;
PWD2="$PWD/2/*" ;
DIFFS=0 ;
NODIFFS=0 ;
printf "Starting comparison on $PWD1 @ $(date)\n\n" ;
FILES_A=$(find ${PWD1} -type f) ;
FILES_B=$(find ${PWD2} -type f) ;
for A_FILE in ${FILES_A[*]} ; do
for B_FILE in ${FILES_B[*]} ; do
if ! cmp ${A_FILE} ${B_FILE} 1>/dev/null ; then
printf "$A_FILE & $B_FILE <- DIFFER.\n" ;
((++DIFFS)) ;
else
printf "\n-> SAME: $A_FILE & $B_FILE\n" ;
((++NODIFFS)) ;
fi ;
done ;
done ;
printf "\n= $DIFFS <= differences detected - & - $NODIFFS <= exact matches.\n" ;
printf "\nCompleted comparison @ $(date)\n" ;