ฉันต้องการสร้างรายการไฟล์ที่มี:
- ชื่อเดียวกัน
- เนื้อหาที่แตกต่าง
ในไดเรกทอรี (รวมถึงไดเรกทอรีลูกและเนื้อหาทั้งหมด)
วิธีการทำ? ทุบตี Perl อะไรก็ได้
ดังนั้นไฟล์สองไฟล์ที่มีชื่อเหมือนกันและเนื้อหาเดียวกันไม่ควรแสดงขึ้นมา
ฉันต้องการสร้างรายการไฟล์ที่มี:
ในไดเรกทอรี (รวมถึงไดเรกทอรีลูกและเนื้อหาทั้งหมด)
วิธีการทำ? ทุบตี Perl อะไรก็ได้
ดังนั้นไฟล์สองไฟล์ที่มีชื่อเหมือนกันและเนื้อหาเดียวกันไม่ควรแสดงขึ้นมา
คำตอบ:
อัปเดต: แก้ไขการพิมพ์ผิดในสคริปต์: เปลี่ยน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
s
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
นี่คือสคริปต์ Perl เรียกใช้ในไดเรกทอรีที่ด้านบนของแผนผังที่คุณต้องการค้นหา สคริปต์ขึ้นอยู่กับfind
และmd5
แต่หลังสามารถถูกแทนที่ด้วยsha1
, sum
หรือโปรแกรมอื่น ๆ คร่ำเครียดไฟล์ที่รับข้อมูลเกี่ยวกับ stdin และผลกัญชาบน 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";
}
}
}
finddupเครื่องมือนี้ยังสามารถช่วยคุณในการแสดงรายชื่อไฟล์ที่มีชื่อหรือเนื้อหาเดียวกัน ..
สำหรับผู้ที่ต้องการดูรายการชื่อไฟล์ที่นี่เป็นส่วนที่เกี่ยวข้องของPeter.O 's คำตอบ :
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
ก่อนสคริปต์เพื่อล้างข้อมูลที่ซ้ำกันทั้งหมด