Portál AbcLinuxu, 30. dubna 2025 11:05
use strict; use Cwd; use File::Spec::Functions; my %files = (); my $dir = $ARGV[0] || getcwd(); opendir(DIRHANDLE, $dir); for (readdir(DIRHANDLE)) { my $path = catfile($dir, $_); if (-f $path) { push( @{ $files{-s $path} } , $_); } } delete_singels(\%files); print_dup(\%files); sub delete_singels { my $href = shift; for (keys %$href) { if (scalar @{ $href->{$_} } == 1) { delete $href->{$_}; } } } sub print_dup { my $href = shift; for (keys %$href) { print "Found " . scalar @{ $href->{$_} } . " files with size $_ bytes:\n"; print join("\n", @{ $href->{$_} } ) . "\n\n"; } }Skript můžeme spustit takto:
perl dup.pl Books/PerlPředstavme si, že ve složce
Found 2 files with size 9673854 bytes: OReilly.Perl.Cookbook.pdf Cookbook.pdf Found 3 files with size 2035408 bytes: Higher.Order.Perl.pdf Higher_Order_Perl.pdf HigherOrderPerl.pdfTen samý skript v Ruby:
class Dup def initialize @files = Hash.new {|h,k| h[k] = [] } @dir = ARGV[0] || __dir__ end def read_files Dir.entries(@dir).each do |name| path = File.join(@dir, name) if File.file? path @files[File.size(path)] << name end end delete_singles end def print @files.each do |k,v| puts "Found #{v.length} files" + " with size #{k} bytes:" puts v puts end end private def delete_singles @files.delete_if {|k,v| v.length == 1 } end end d = Dup.new d.read_files d.printa opět:
ruby dup.rb Books/PerlMyslím, že Ruby je na tenhle typ skriptování docela efektivní jazyk.
Tiskni
Sdílej:
require 'pathname'
@dir = ARGV[0] || __dir__
Pathname.new(@dir).children.select(&:file?)
.group_by { |path| File.size(path) }
.tap { |h| h.delete(1) }
.each do |k, v|
puts "Found #{v.length} files with size #{k} bytes:"
puts v
puts
end
my %sizes; $, = "\n"; unshift @{$sizes{-s $_}}, $_ foreach grep -f $_, glob "* .*"; foreach (keys %sizes) { next unless $#{$sizes{$_}}; print 'Found ' . ($#{$sizes{$_}} + 1) . " files with size $_ bytes:\n"; print @{$sizes{$_}}, "\n"; }
<?php // nacita zoznam suborov $list=scandir("."); // zisti velkosti $statistic=array(); foreach($list as $name) if(is_file($name)) { $size=filesize($name); if(isset($statistic[$size])) array_push($statistic[$size], "$name"); else $statistic[$size]=array("$name"); } // vypise foreach($statistic as $size => $items) { $count=count($items); if($count < 2) continue; echo "Size: ${size} B, count: $count\n"; echo implode("\n", $items)."\n"; }
require 'digest/md5' digest = Digest::MD5.hexdigest(File.read(f))
supr skripty :D ;D
teda já jako perlu a ruby vubec nerozumim ale vidim žeto neni koronarýma tak jakoby lajkuju :D :D ;D ;D
perl -e 'use File::Slurp; $x{$_}++ foreach (map({ -s $_ } read_dir("."))); while (my ($s, $c) = each(%x)) { print("size=$s count=$c\n") if ($c > 1); }'
Arrays.stream(new File(".").listFiles())
.map(file -> file.length())
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.forEach((s, c) -> if (c > 1) System.out.printf("size=%s count=%c\n", s, c));
Kratší než oba původní příklady (i když ty by šly taky zkrátit, viz výše) a přesto IMHO čitelnější. Ta čitelnost se pak objeví v případě větší komplexity, teď je to přece jen dost primitivní podle jednoho klíče.
#!/usr/bin/env python3 from pathlib import Path from itertools import groupby files = sorted((file.stat().st_size, file) for file in Path('.').iterdir() if file.is_file()) groups = (same_files for size, group in groupby(files, lambda x: x[0]) if len(same_files := list(group)) > 1) for group in groups: print('Found {count} files with size {size} bytes:\n{files}\n'.format( count=len(group), size=group[0][0], files='\n'.join(file[1].name for file in group) ))Omlouvám se za použití operátoru
:=
.
#!/usr/bin/env bash files="$(find . -type f -printf '%s %f\n' | sort -n)" sizes="$(cut -f 1 -d ' ' <<< "$files" | uniq --repeated)" for size in $sizes; do count="$(grep -c "^$size " <<< "$files")" names="$(grep "^$size " <<< "$files" | cut -f 2 -d ' ')" printf 'Found %s files with size %s bytes:\n%s\n\n' "$count" "$size" "$names" done
find -type f -exec md5sum {} \; | sort |uniq --all-repeated=separate -w32
(teda normalne ty md5sum mam nekde ulozene a pracuju s nima opakovane, takze to jsou bezne prikazy 2, jeden vytvori seznam hashu souboru, druhy hleda duplicity)
Já si například pravidelně ukládám shasumy všech souborů na datovém úložišti nikoliv pro hledání duplicit, ale proto, abych věděl, jestli se ty soubory mění nebo ne.Tohle dělám taky, akorát pouze při zálohování celého /home oddílu. Udělám snapshot kvůli konzistenci, v něm nechám spočítat checksum všeho a pak spustím zálohu. Ten checksum soubor mám pak jak lokálně tak u té zálohy, takže v případě poškozeného binárního souboru co se normálně moc nemění jsem schopen rychle dohledat v které záloze mám předchozí verzi. Ale dělám to primárně kvůli kontrole konzistence zálohy a obnovených dat.
když jakoby dělá jenom hledání duplicitních souborů někde u sebe na disku tak vodolnost toho hashe neni zese jako moc důležitá ne?? :O :O
joa neni md5 taky trošičku rychlejší/lacinější než sha512????? :O ;D
joa neni md5 taky trošičku rychlejší/lacinější než sha512Netuším a je to jedno, stejně se čeká na storage, spočítat to je rychlejší, než číst z disku. Pokud má dotyčný data v 1TB ramdisku, tak to nemusí platit, ale v tom případě zřejmě bude mít něco jako EPIC a tak si to snadno může paralelizovat. Jinak pokud někomu vadí zrovna sha512, tak existují jiné, neprolomené a velmi rychlé funkce (třeba rodina sha3 - kde byla rychlost z jedním z požadavků soutěže).
ok to zní rozumě :D ;D
find . -type f -size +100M -print0 | xargs -0 rdfind -ignoreempty true -checksum sha1 -makehardlinks true -outputname ./rdfind100M_results.txt -dryrun false > ./rdfind100_stdout.txt 2>&1
ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.