Dateien mit demselben Namen, aber unterschiedlichem Inhalt suchen?

9

Ich möchte eine Liste von Dateien erstellen, die Folgendes haben:

  • Gleicher Name
  • Unterschiedlicher Inhalt

in einem Verzeichnis (einschließlich aller untergeordneten Verzeichnisse und Inhalte).

Wie macht man? Bash, Perl, alles ist in Ordnung.

Daher sollten zwei Dateien mit demselben Namen und demselben Inhalt nicht angezeigt werden.

Nicolas Raoul
quelle
Angenommen, es gibt drei Dateien mit demselben Namen und zwei der drei sind identisch?
Kyle Jones
@ KyleJones: "Drei Dateien mit dem gleichen Namen und zwei der drei sind identisch"> Dann sollte dieser Dateiname zur Liste hinzugefügt werden
Nicolas Raoul

Antworten:

8

Update: Tippfehler im Skript behoben: geändert print $NFin print $3; räumte auch auf und fügte einige Kommentare hinzu.

Unter der Annahme , Dateinamen enthalten nicht \ndie folgenden druckt eine sortierte Liste , die Brüche (wie in: Steuerabschnitt bricht ) bei einzigartigen file name, einzigartig md5sumund zeigt die entsprechende Gruppe von Dateipfaden.

#!/bin/bash

# Choose which script to use for the final awk step 
out_script=out_all

# Print all duplicated file names, even when md5sum is the same 
out_all='{ if( p1 != $1 ) { print nl $1; print I $2 }
      else if( p2 != $2 ) { print I $2 }
      print I I $3; p1=$1; p2=$2; nl="\n" }
   END { printf nl}'

# Print only duplicated file names which have multiple md5sums.
out_only='{ if( p1 != $1 ) { if( multi ) { print pend }
                             multi=0; pend=$1 "\n" I $2 "\n" }
       else if( p2 != $2 ) { multi++; pend=pend I $2 "\n" } 
       pend=pend I I $3 "\n"; p1=$1; p2=$2 } 
   END { if( multi ) print pend }'

# The main pipeline 
find "${1:-.}" -type f -name '*' |  # awk for duplicate names
awk -F/ '{ if( name[$NF] ) { dname[$NF]++ }
           name[$NF]=name[$NF] $0 "\n" } 
     END { for( d in dname ) { printf name[d] } 
   }' |                             # standard md5sum output 
xargs -d'\n' md5sum |               # " "==text, "*"==binary
sed 's/ [ *]/\x00/' |               # prefix with file name  
awk -F/ '{ print $3 "\x00" $0 }' |  # sort by name. md5sum, path 
sort |                              # awk to print result
awk -F"\x00" -v"I=   " "${!out_script}"

Ausgabe, die nur Dateinamen mit mehreren md5 s anzeigt

afile.html
   53232474d80cf50b606069a821374a0a
      ./test/afile.html
      ./test/dir.svn/afile.html
   6b1b4b5b7aa12cdbcc72a16215990417
      ./test/dir.svn/dir.show/afile.html

Ausgabe mit allen gleichnamigen Dateien.

afile.html
   53232474d80cf50b606069a821374a0a
      ./test/afile.html
      ./test/dir.svn/afile.html
   6b1b4b5b7aa12cdbcc72a16215990417
      ./test/dir.svn/dir.show/afile.html

fi    le.html
   53232474d80cf50b606069a821374a0a
      ./test/dir.svn/dir.show/fi    le.html
      ./test/dir.svn/dir.svn/fi    le.html

file.html
   53232474d80cf50b606069a821374a0a
      ./test/dir.show/dir.show/file.html
      ./test/dir.show/dir.svn/file.html

file.svn
   53232474d80cf50b606069a821374a0a
      ./test/dir.show/dir.show/file.svn
      ./test/dir.show/dir.svn/file.svn
      ./test/dir.svn/dir.show/file.svn
      ./test/dir.svn/dir.svn/file.svn

file.txt
   53232474d80cf50b606069a821374a0a
      ./test/dir.show/dir.show/file.txt
      ./test/dir.show/dir.svn/file.txt
      ./test/dir.svn/dir.show/file.txt
      ./test/dir.svn/dir.svn/file.txt
Peter.O
quelle
1

Hier ist ein Perl-Skript. Führen Sie es in dem Verzeichnis oben im Baum aus, in dem Sie suchen möchten. Das Skript ist abhängig von findund md5, aber die letztere kann ersetzt werden sha1, sumoder ein beliebiges anderes Datei - Hashing - Programm , das auf stdin Eingang akzeptiert und gibt einen Hash auf stdout.

use strict;

my %files;
my %nfiles;
my $HASHER = 'md5';

sub
print_array
{
    for my $x (@_) {
        print "$x\n";
    }
}

open FINDOUTPUT, "find . -type f -print|" or die "find";

while (defined (my $line = <FINDOUTPUT>)) {
    chomp $line;
    my @segments = split /\//, $line;
    my $shortname = pop @segments;
    push @{ $files{$shortname} }, $line;
    $nfiles{$shortname}++;
}

for my $shortname (keys %files) {
    if ($nfiles{$shortname} < 2) {
        print_array @{ $files{$shortname} };
        next;
    }
    my %nhashes;
    my %revhashes;
    for my $file (@{ $files{$shortname} }) {
        my $hash = `$HASHER < $file`;
        $revhashes{$hash} = $file;
        $nhashes{$hash}++;
    }
    for my $hash (keys %nhashes) {
        if ($nhashes{$hash} < 2) {
            my $file = $revhashes{$hash};
            print "$file\n";
        }
    }
}
Kyle Jones
quelle
1

finddup Dieses Tool kann Ihnen auch dabei helfen, Dateien mit demselben Namen oder Inhalt aufzulisten.

user379997
quelle
1

Für diejenigen , die nur eine Liste von Dateinamen sehen möchten, hier ist der relevante Teil der Peter.O ‚s Antwort :

find "${1:-.}" -type f -name '*' | 
awk -F/ '{ if( name[$NF] ) { dname[$NF]++ }
       name[$NF]=name[$NF] $0 "\n" } 
 END { for( d in dname ) { printf name[d] "\n" } 

} '

Ich brauche keine md5sums, da ich fslint-guivor dem Skript alle Duplikate lösche .

int_ua
quelle
Auf meinem Mac werden die doppelten Dateien mit demselben Namen und demselben Inhalt
angezeigt