मैं उन फ़ाइलों की एक सूची तैयार करना चाहता हूं जिनमें:
- एक ही नाम
- अलग सामग्री
एक निर्देशिका में (सभी बच्चों की निर्देशिका और सामग्री सहित)।
कैसे करें? बैश, पर्ल, कुछ भी ठीक है।
इसलिए, समान नाम और समान सामग्री वाली दो फ़ाइलों को नहीं दिखाना चाहिए।
मैं उन फ़ाइलों की एक सूची तैयार करना चाहता हूं जिनमें:
एक निर्देशिका में (सभी बच्चों की निर्देशिका और सामग्री सहित)।
कैसे करें? बैश, पर्ल, कुछ भी ठीक है।
इसलिए, समान नाम और समान सामग्री वाली दो फ़ाइलों को नहीं दिखाना चाहिए।
जवाबों:
अद्यतन: स्क्रिप्ट में एक टाइपो तय: बदल print $NF
गया print $3
; चीजों को भी तस्लीम किया और कुछ टिप्पणियां भी जोड़ीं।
मान लें कि फ़ाइल नाम शामिल नहीं हैं \n
, तो निम्न छांटे गए सूची को प्रिंट करता है , जो टूट जाता है (जैसे: अनुभाग नियंत्रण टूट जाता है ) अद्वितीय file name
, अद्वितीय पर md5sum
, और फ़ाइल पथों के संबंधित समूह को दिखाता है।
#!/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}"
आउटपुट दिखा ही साथ फ़ाइल नाम कई md5
रों
afile.html
53232474d80cf50b606069a821374a0a
./test/afile.html
./test/dir.svn/afile.html
6b1b4b5b7aa12cdbcc72a16215990417
./test/dir.svn/dir.show/afile.html
आउटपुट सभी फ़ाइलों को एक ही नाम से दिखा रहा है ।
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
यहाँ एक पर्ल स्क्रिप्ट है। आप जिस पेड़ को खोजना चाहते हैं उसके शीर्ष पर निर्देशिका में इसे चलाएं। स्क्रिप्ट पर निर्भर करता है find
और md5
, लेकिन उत्तरार्द्ध के साथ प्रतिस्थापित किया जा सकता है sha1
, sum
या किसी अन्य फ़ाइल हैशिंग प्रोग्राम जो स्टड पर इनपुट स्वीकार करता है और स्टैडआउट पर एक हैश का आउटपुट देता है।
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";
}
}
}
finddup यह टूल आपको समान नाम या सामग्री वाली फ़ाइलों को सूचीबद्ध करने में भी मदद कर सकता है।
उन लोगों के लिए जो केवल फ़ाइल नाम की एक सूची देखना चाहते हैं, यहाँ पीटरओ के उत्तर का प्रासंगिक हिस्सा है :
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" }
} '
मुझे md5sums की आवश्यकता नहीं है क्योंकि मैं fslint-gui
सभी डुप्लिकेट को साफ़ करने के लिए स्क्रिप्ट से पहले उपयोग करता हूं ।