Wie kann ich verschiedene Dateien vergleichen, ohne sie zu öffnen?

Wie kann ich verschiedene Dateien vergleichen, ohne sie zu öffnen?

Ich habe zwei Verzeichnisse A und B; jedes enthält viele Unterverzeichnisse

geom001, geom002 ....etc

jedes Unterverzeichnis enthält eine Datei mit dem Namen „Results“. Ich möchte, ohne eine davon zu öffnen, jede Datei in A mit jeder Datei in B vergleichen und herausfinden, ob es in A eine oder mehrere Dateien gibt, die einer oder mehreren Dateien in B ähnlich sind. Wie kann ich einen Befehl wie den folgenden in einer Schleife verwenden, um alle Dateien zu durchsuchen?

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

Antwort1

Wenn die Dateien genau gleich sind, md5sumsind auch ihre s genau gleich. Sie können also Folgendes verwenden:

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

Eine MD5-Summe ist immer genau 128 Bit (oder 16 Byte oder 32 Hexadezimalziffern) lang, und die md5sumProgrammausgabe verwendet Hexadezimalziffern. Daher verwenden wir die -w32Option im uniqBefehl, um nur die ersten 32 Zeichen in jeder Zeile zu vergleichen.

Dies drucktalleDateien mit einer nicht eindeutigen MD5-Summe, also Duplikate.

HINWEIS: Dadurch werden doppelte Dateien erkannt, egal wo sie sich in A/ oder B/ befinden. Wenn also /A/subdir1/fileund A/subdir2/otherfileidentisch sind, werden sie trotzdem gedruckt. Wenn mehrere Duplikate vorhanden sind, werden sie alle gedruckt.

Sie können die MD5-Summen aus der Ausgabe entfernen, indem Sie sie beispielsweise in „ awk '{print $2}'oder“ mit cut„oder“ sedusw. weiterleiten. Ich habe sie in der Ausgabe belassen, da sie für die weitere Verarbeitung ein nützlicher Schlüssel für ein assoziatives Array (auch als „Hash“ bezeichnet) in „ awkoder perl“ usw. sind.

Antwort2

Ich denke, damit kommen Sie nah heran. Es listet die CMP-Ausgabe für alle Dateien mit dem Namen „Results“ in A auf, verglichen mit allen Dateien mit dem Namen „Results“ in B.

find ./A -name results | xargs -I REPLACESTR find ./B -name results -exec cmp REPLACESTR {} \;

Antwort3

Die scheinbare Herausforderung der Frage/Anfrage liegt vielleicht im Rekursionsaspekt.

Vorausgesetzt, es cmphandelt sich um ein geeignetes Dienstprogramm und die beiden zu vergleichenden Ordner/Verzeichnisse 1haben 2dieselbe Struktur (d. h. dieselben Dateien und Ordner) und befinden sich im selben Stammpfad, können Sie Folgendes versuchen:

#!/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" ;

AKTUALISIEREN:

Anschließend folgt – auf Grundlage des erhaltenen zusätzlichen Feedbacks – ein weiteres Skript zum bedingungslosen Vergleichen aller Dateien im Verzeichnis 1mit 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" ;

verwandte Informationen