Как сравнить разные файлы, не открывая их?

Как сравнить разные файлы, не открывая их?

У меня есть два каталога A и B; каждый из них содержит множество подкаталогов.

geom001, geom002 ....etc

каждый подкаталог содержит файл с именем results. Я хочу сравнить, не открывая ни один из них, каждый файл в A с каждым файлом в B и найти, есть ли файл или несколько в A, похожие на один или несколько файлов в B. Как я могу использовать команду, подобную следующей, в цикле для поиска по всем файлам?

cmp --silent  file1 file2  || echo "file1 and file2 are different"

решение1

Если файлы абсолютно одинаковые, то их md5sums будут абсолютно одинаковыми, поэтому вы можете использовать:

find A/ B/ -type f -exec md5sum {} + | sort | uniq -w32 -D

md5sum всегда имеет длину ровно 128 бит (или 16 байт или 32 шестнадцатеричных цифры), а md5sumвывод программы использует шестнадцатеричные цифры. Поэтому мы используем -w32опцию в uniqкоманде, чтобы сравнивать только первые 32 символа в каждой строке.

Это напечатаетвсефайлы с неуникальной суммой md5, т.е. дубликаты.

ПРИМЕЧАНИЕ: это обнаружит дубликаты файлов, независимо от того, где они находятся в A/ или B/ - поэтому, если /A/subdir1/fileи A/subdir2/otherfileодинаковы, они все равно будут напечатаны. Если есть несколько дубликатов, они все будут напечатаны.

Вы можете удалить md5sums из выходных данных, передав их, например, в awk '{print $2}'or с помощью cutor sedи т. д. Я оставил их в выходных данных, потому что они являются полезным ключом для ассоциативного массива (он же «хэш») в awkor perlи т. д. для дальнейшей обработки.

решение2

Я думаю, это приблизит вас к цели. Он выведет вывод cmp для всех файлов с именами results в A в сравнении со всеми файлами с именами results в B.

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" ;

Связанный контент