
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, md5sum
sind 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 md5sum
Programmausgabe verwendet Hexadezimalziffern. Daher verwenden wir die -w32
Option im uniq
Befehl, 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/file
und A/subdir2/otherfile
identisch 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“ sed
usw. 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 „ awk
oder 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 cmp
handelt sich um ein geeignetes Dienstprogramm und die beiden zu vergleichenden Ordner/Verzeichnisse 1
haben 2
dieselbe 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 1
mit 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" ;