C'è un modo semplice per sostituire i file duplicati con hardlink?


137

Sto cercando un modo semplice (un comando o una serie di comandi, probabilmente che coinvolge find) per trovare file duplicati in due directory e sostituire i file in una directory con collegamenti fisici dei file nell'altra directory.

Ecco la situazione: questo è un file server su cui più persone memorizzano file audio, ogni utente ha la propria cartella. A volte più persone hanno copie degli stessi identici file audio. In questo momento, questi sono duplicati. Vorrei farlo in modo che siano hardlink, per risparmiare spazio sul disco rigido.


20
Un problema che potresti incontrare con i collegamenti fisici è se qualcuno decide di fare qualcosa per uno dei suoi file musicali che hai hard-linked potrebbe inavvertitamente influenzare l'accesso di altre persone alla loro musica.
Steven D,

4
un altro problema è che due diversi file contenenti "Some Really Great Tune", anche se presi dalla stessa fonte con lo stesso codificatore, molto probabilmente non saranno identici bit per bit.
msw,

3
migliore sollution potrebbe essere quello di avere una cartella musicale pubblica ...
Stefan


1
@tante: l'uso di symlink non risolve alcun problema. Quando un utente "elimina" un file, il numero di collegamenti ad esso diminuisce, quando il conteggio raggiunge lo zero, i file vengono realmente eliminati, tutto qui. Quindi la cancellazione non è un problema con i file hardlinked, l'unico problema è un utente che tenta di modificare il file (in effetti non è possibile) o di sovrascriverlo (abbastanza possibile se si è effettuato l'accesso).
maaartino

Risposte:


41

C'è uno script perl su http://cpansearch.perl.org/src/ANDK/Perl-Repository-APC-2.002/eg/trimtrees.pl che fa esattamente quello che vuoi:

Attraversa tutte le directory nominate sulla riga di comando, calcola i checksum MD5 e trova i file con MD5 identico. SE sono uguali, fai un vero confronto se sono davvero uguali, sostituisci il secondo di due file con un collegamento reale al primo.


Sembra perfetto , grazie !! Lo proverò e accetterò se funziona come descritto!
Josh,

3
Questo ha fatto esattamente quello che ho chiesto. Tuttavia, credo che ZFS con dedup alla fine sarà il modo di fare, dal momento che ho scoperto che i file presentavano lievi differenze, quindi solo alcuni potevano essere collegati.
Josh,

11
Ho votato a fondo, ma dopo aver fatto qualche ricerca in più, non l'ho fatto. rdfindè disponibile tramite i gestori pacchetti per TUTTE le principali piattaforme (os x, linux, (cyg) win, solaris) e funziona a una velocità nativa incredibile. Quindi controlla la risposta qui sotto.
Oligofren,

@oligofren Stavo pensando lo stesso, ma poi ho colpito [Errno 31] Too many links. Questo script sembra essere l'unica cosa che lo gestisce.
phunehehe,

5
Il checksum di ogni singolo file, anziché solo i file in cui ne esiste almeno un altro con dimensioni identiche, è inutilmente inefficiente (e inutilmente soggetto a collisioni di hash).
Charles Duffy,

85

rdfindfa esattamente quello che chiedi (e nell'ordine johny why lists). Permette di eliminare i duplicati, sostituirli con collegamenti soft o hard. In combinazione con symlinkste puoi anche rendere il collegamento simbolico sia assoluto che relativo. Puoi anche scegliere l'algoritmo di checksum (md5 o sha1).

Da quando è stato compilato è più veloce della maggior parte delle soluzioni con script: timesu una cartella da 15 GiB con 2600 file sul mio Mac Mini del 2009 restituisce questo

9.99s user 3.61s system 66% cpu 20.543 total

(usando md5).

Disponibile nella maggior parte dei gestori di pacchetti (ad es. MacPorts per Mac OS X).


11
+1 L'ho usato rdfinde mi è piaciuto. Ha -dryrun trueun'opzione che ti farà sapere cosa avrebbe fatto. Sostituire i duplicati con hard link è semplice come -makehardlinks true. Ha prodotto un bel registro e mi ha fatto sapere quanto spazio è stato liberato. Inoltre, secondo il benchmark dell'autore , rdfind è più veloce di duff e fslint.
Daniel Trebbien,

oooh, carino. Usavo fdupes, ma la sua opzione -L per i duplicati hardlinking manca nell'ultimo Ubuntu 14.10. Era piuttosto lento e non esisteva per Homebrew su OSX, quindi questa risposta è decisamente migliore. Grazie!
Oligofren,

Algoritmo molto intelligente e veloce.
ndemou,

2
Sospetto che le prestazioni di questo strumento abbiano più a che fare con l'algoritmo stesso e meno con se sia uno strumento compilato o uno script. Per questo tipo di operazione, il disco sarà il collo di bottiglia quasi sempre. Fintanto che gli strumenti con script assicurano di avere un'operazione di I / O asincrona in corso durante la masterizzazione della CPU su checksum, devono eseguire circa un binario nativo.
cdhowie,

rdfind dipende molto dal nuovo sistema operativo e dal compilatore. (non funzionerà su CentOS 6.x senza una ricostruzione quasi completa degli strumenti di sviluppo)
Cosmo F

49

Usa lo fdupesstrumento:

fdupes -r /path/to/folderti dà un elenco di duplicati nella directory (-r lo rende ricorsivo). L'output è simile al seguente:


nomefile1
nomefile2

nomefile3
nomefile4
nomefile5


con nomefile1 e nomefile2 identici e nomefile3, nomefile4 e nomefile5 uguali.


1
Nota Ubuntu: da settembre 2013, non ha avuto una versione stabile (è su 1.50-PR2-3), quindi l'aggiornamento non appare ancora in Ubuntu.
Stuart Axon,

11
Ho appena provato a installare fdupes_1.50-PR2-4 sia su Ubuntu che su Debian, né ha il flag -L. Fortunatamente costruire da github.com/tobiasschulz/fdupes è stato semplicissimo.
neu242,

3
Prova rdfindcome fdupes, ma più veloce e disponibile anche su OS X e Cygwin.
Oligofren,

6
fdupessembra trovare solo duplicati, non sostituirli con hardlink, quindi non una risposta alla domanda IMO.
Calimo,

2
C'è uno strumento simile chiamato su jdupescui si basa fdupes, ma può anche sostituire i file duplicati con symlink ( -l), hardlink ( -L) o indicare a btrfs di deduplicare i blocchi a livello di filesystem ( -B, se si utilizza btrfs).
Marius Gedminas,

23

1
Bel suggerimento, sto usando un codice base regolare.google.com/p/hardlinkpy ma questo non è stato aggiornato per un po '...
Meduz,

2
Questo sembra essere simile all'originale hardlinksu Fedora / RHEL / ecc.

1
hardlinkè ora un binario nativo in molti sistemi di pacchetti Linux (dal ~ 2014) ed estremamente veloce. Per i file 1,2M (320 GB), sono bastati 200 secondi (collegando circa il 10% dei file).
Marcel Waldvogel,

FWIW, quanto sopra è hardlinkstato creato da Julian Andres Klode mentre Fedora è hardlinkstata creata da Jakub Jelinek (fonte: pagure.io/hardlink - Nome pacchetto Fedora: hardlink)
maxschlepzig


14

Poiché l'obiettivo principale è risparmiare spazio su disco, esiste un'altra soluzione: la deduplicazione (e probabilmente la compressione) a livello di file system. Rispetto alla soluzione di collegamento reale, non ha il problema di influenzare inavvertitamente altri file collegati.

ZFS ha dedup (a livello di blocco, non a livello di file) dalla versione di pool 23 e compressione da molto tempo fa. Se stai usando Linux, puoi provare zfs-fuse , o se usi BSD, è nativamente supportato.


Questo è probabilmente il modo in cui andrò alla fine, tuttavia, l'implementazione ZFS di BSD deduce? Pensavo di no.
Josh

Inoltre, il filesystem HAMMER su DragonFlyBSD ha il supporto per la deduplicazione.
hhaamu,

14
Il dedup ZFS non è amico di nessuno. Laddove ZFS consiglia 1 GB di RAM per 1 TB di spazio su disco utilizzabile, sei fuori di testa se cerchi di utilizzare il dedup con meno di 32 GB di RAM per 1 TB di spazio su disco utilizzabile. Ciò significa che per un mirror da 1 TB, se non si dispone di un ram da 32 Gb, è probabile che prima o poi si verifichino condizioni di bomba di memoria che arrestano la macchina a causa della mancanza di ram. Ci sono stato, fatto questo, ancora in fase di recupero dal PTSD.
assassino il

4
Per evitare i requisiti eccessivi di RAM con deduplicazione online (ovvero, controllare ogni scrittura), btrfsutilizza la deduplicazione batch o offline ( eseguila
Marcel Waldvogel

3
Aggiornamento sette anni dopo: alla fine sono passato a ZFS e ho provato la deduplicazione: ho scoperto che i suoi requisiti di RAM erano davvero molto alti. L'uso scaltro delle istantanee di ZFS ha fornito la soluzione che ho finito per usare. (Copia la musica di un utente, l'istantanea e il clone, copia la musica del secondo utente nel clone usando in rsync --inplacemodo che siano memorizzati solo i blocchi modificati)
Josh


5

Per trovare file duplicati puoi usare duff .

Duff è un'utilità della riga di comando Unix per trovare rapidamente duplicati in un determinato set di file.

Esegui semplicemente:

duff -r target-folder

Per creare automaticamente collegamenti a tali file, è necessario analizzare l'output di duff con bash o qualche altro linguaggio di scripting.


Davvero lento - vedi rdfind.pauldreik.se/#g0.6
ndemou,

5
aptitude show hardlink

Descrizione: Hardlink più copie dello stesso file Hardlink è uno strumento che rileva più copie dello stesso file e le sostituisce con hardlink.

L'idea è stata presa da http://code.google.com/p/hardlinkpy/ , ma il codice è stato scritto da zero e concesso in licenza con la licenza MIT. Pagina iniziale: http://jak-linux.org/projects/hardlink/


L'unico programma menzionato qui disponibile per Gentoo senza smascheramento e con supporto hardlink, grazie!
Jorrit Schippers,

4

Ho usato molti degli strumenti di hardlinking per Linux menzionati qui. Anch'io sono bloccato con ext4 fs, su Ubuntu, e ho usato i suoi cp -l e -s per hard / softlinking. Ma ultimamente ho notato la copia leggera nella pagina man di cp , che implicherebbe di risparmiare spazio su disco ridondante fino a quando un lato non viene modificato:

   --reflink[=WHEN]
          control clone/CoW copies. See below

       When  --reflink[=always]  is specified, perform a lightweight copy, where the 
data blocks are copied only when modified.  If this is not possible the
       copy fails, or if --reflink=auto is specified, fall back to a standard copy.

Penso che aggiornerò il mio cpalias per includere sempre il --reflink=autoparametro ora
Marcos

1
Ext4 supporta davvero --reflink?

7
Questo è supportato su btrfs e OCFS2. È possibile solo su filesystem copy-on-write, che ext4 non lo è. btrfs sta davvero dando forma. Adoro usarlo a causa del reflink e delle istantanee, ti rende meno spaventato di fare operazioni di massa su grandi alberi di file.
clacke,

3

Mi sembra che controllare prima il nome del file potrebbe velocizzare le cose. Se due file non hanno lo stesso nome file, in molti casi non li considero duplicati. Sembra che il metodo più rapido sarebbe quello di confrontare, in ordine:

  • nome del file
  • taglia
  • checksum md5
  • contenuto byte

Qualche metodo fa questo? Guardate duff, fdupes, rmlint, fslint, etc.

Il seguente metodo è stato votato per primo su commandlinefu.com : Trova file duplicati (prima in base alle dimensioni, quindi all'hash MD5)

È possibile aggiungere il confronto dei nomi di file come primo passo, la dimensione come secondo passo?

find -not -empty -type f -printf "%s\n" | sort -rn | uniq -d | \
  xargs -I{} -n1 find -type f -size {}c -print0 | xargs -0 md5sum | \
  sort | uniq -w32 --all-repeated=separate

3
Ho usato duff, fdupese rmlintconsiglio vivamente ai lettori di esaminare il terzo di questi . Ha un eccellente set di opzioni (e documentazione). Con esso, sono stato in grado di evitare molta della post-elaborazione che avevo bisogno di usare con gli altri strumenti.
dubiousjim,

3
Nella mia pratica, il nome file è il fattore meno affidabile da guardare e l'ho rimosso completamente da ogni sforzo che faccio un de-duping. Quanti install.shfile è possibile trovare su un sistema attivo? Non riesco a contare il numero di volte in cui ho salvato un file e ho avuto uno scontro di nomi, con qualche rinominazione al volo per salvarlo. Rovescio: non ho idea di quante volte ho scaricato qualcosa da fonti diverse, in giorni diversi, solo per scoprire che sono lo stesso file con nomi diversi. (Il che uccide anche l'affidabilità del timestamp.) 1: Dimensione, 2: Digest, 3: contenuto byte.
Gypsy Spellweaver,

@GypsySpellweaver: (1) dipende dal caso d'uso personale, non sei d'accordo? Nel mio caso, ho più ripristini da più backup, in cui esistono file con lo stesso nome e contenuto in diverse cartelle di ripristino. (2) Il tuo commento sembra assumere solo il confronto del nome file . Non stavo suggerendo di eliminare altri controlli.
johny perché

2

Dato che non sono un fan di Perl, ecco una versione bash:

#!/bin/bash

DIR="/path/to/big/files"

find $DIR -type f -exec md5sum {} \; | sort > /tmp/sums-sorted.txt

OLDSUM=""
IFS=$'\n'
for i in `cat /tmp/sums-sorted.txt`; do
 NEWSUM=`echo "$i" | sed 's/ .*//'`
 NEWFILE=`echo "$i" | sed 's/^[^ ]* *//'`
 if [ "$OLDSUM" == "$NEWSUM" ]; then
  echo ln -f "$OLDFILE" "$NEWFILE"
 else
  OLDSUM="$NEWSUM"
  OLDFILE="$NEWFILE"
 fi
done

Questo trova tutti i file con lo stesso checksum (siano essi grandi, piccoli o già collegati) e li collega insieme.

Questo può essere notevolmente ottimizzato per ripetute esecuzioni con flag di ricerca aggiuntivi (ad es. Dimensione) e una cache di file (quindi non è necessario ripetere i checksum ogni volta). Se qualcuno è interessato alla versione più intelligente e più lunga, posso pubblicarla.

NOTA: Come accennato in precedenza, i collegamenti fisici funzionano fintanto che i file non necessitano mai di modifiche o devono essere spostati tra i file system.


Come posso modificare il tuo script, in modo che invece di collegarlo in modo definitivo, eliminerà solo i file duplicati e aggiungerà una voce a un file CSV il file eliminato -> File allineato. . ???
MR.GEWA,

Sicuro. La linea di collegamento reale: echo ln -f "$ OLDFILE" "$ NEWFILE" Sostituisce semplicemente il file duplicato con un collegamento reale, quindi è possibile cambiarlo con $ NEWFILE.
seren

e come nella riga successiva, scrivi in ​​qualche file di testo in qualche modo $ OLDFILE-> NEWFILE ???
MR.GEWA,

Ah, giusto. Sì, aggiungi una riga dopo rm come: echo "$ NEWFILE" >> /var/log/deleted_duplicate_files.log
seren

2
Non tentare di reinventare la ruota. Ci sono soluzioni più mature disponibili, ad esempio rdfind, che funzionano a velocità native e richiedono solo brew install rdfindo apt-get install rdfindper essere installate.
Oligofren,

1

Ho realizzato uno script Perl che fa qualcosa di simile a quello di cui stai parlando:

http://pastebin.com/U7mFHZU7

Fondamentalmente, attraversa solo una directory, calcolando la somma SHA1 dei file in essa contenuti, eseguendo l'hashing e collegando le corrispondenze. È utile in molte, molte occasioni.


2
Spero di provare presto ... perché non caricarlo su CPAN ... App :: ricollegamento o qualcosa del genere
xenoterracide

2
@xenoterracide: a causa di tutte le soluzioni simili e più mature già esistenti. vedere le altre risposte, in particolare rdfind.
Oligofren,

1
@oligofren Non dubito che esistano soluzioni migliori. TMTOWTDI credo.
anfetamachina,



1

jdupes è stato menzionato in un commento ma merita una sua risposta, poiché è probabilmente disponibile nella maggior parte delle distribuzioni e funziona abbastanza velocemente (ha appena liberato 2,7 GB di una partizione da 158 GB (unità SSD) al 98% in circa un minuto):

jdupes -rL /foo/bar

0

Se esegui hardlink, presta attenzione ai diritti su quel file. Avviso, proprietario, gruppo, modalità, attributi estesi, ora e ACL (se si utilizza questo) sono memorizzati in INODE. Solo i nomi dei file sono diversi perché sono memorizzati nella struttura della directory e altri punti sulle proprietà INODE. Questa causa, tutti i nomi di file collegati allo stesso inode, hanno gli stessi diritti di accesso. Dovresti impedire la modifica di quel file, perché qualsiasi utente può danneggiare il file ad altri. È semplice. È sufficiente che qualsiasi utente metta altri file con lo stesso nome. Il numero di nodo viene quindi salvato e il contenuto del file originale viene distrutto (sostituito) per tutti i nomi hardlink.

Il modo migliore è la deduplicazione a livello di filesystem. Puoi usare BTRFS (molto popolare l'ultima volta), OCFS o in questo modo. Guarda la pagina: https://en.wikipedia.org/wiki/Comparison_of_file_systems , in particolare nella tabella Funzionalità e deduplicazione dei dati di colonna. Puoi fare clic e ordinare :)

Guarda in particolare il filesystem ZFS. Questo è disponibile come FUSE, ma in questo modo è molto lento. Se si desidera il supporto nativo, consultare la pagina http://zfsonlinux.org/ . Quindi è necessario patch kernel e quindi installare zfs tools per managament. Non capisco, perché Linux non supporta come driver, è un modo per molti altri sistemi operativi / kernel.

I file system supportano la deduplicazione in 2 modi, file deduplicati o blocchi. ZFS supporta il blocco. Ciò significa che è possibile deduplicare lo stesso contenuto che si ripete nello stesso file. L'altro modo è il momento in cui i dati vengono deduplicati, questo può essere online (zfs) o offline (btrfs).

Si noti che la deduplicazione consuma RAM. Questo è il motivo per cui la scrittura di file nel volume ZFS montato con FUSE causa prestazioni notevolmente lente. Questo è descritto nella documentazione. Ma puoi impostare on / off la deduplicazione sul volume online. Se vedi che tutti i dati devono essere deduplicati, devi semplicemente attivare la deduplicazione, riscrivere alcuni file su qualsiasi temporaneo e infine sostituirli. dopo questo è possibile disattivare la deduplicazione e ripristinare le prestazioni complete. Naturalmente, è possibile aggiungere alla memoria tutti i dischi cache. Questo può essere molto veloce ruotare dischi o dischi SSD. Naturalmente questo può essere un disco molto piccolo. Nel lavoro reale questo è il sostituto della RAM :)

Sotto Linux dovresti prenderti cura di ZFS perché non tutto funziona come dovrebbe, specialmente quando gestisci il filesystem, fai uno snapshot ecc. Ma se fai la configurazione e non la cambi, tutto funziona correttamente. Altrimenti, dovresti cambiare Linux in opensolaris, supporta nativamente ZFS :) Ciò che è molto bello con ZFS è che funziona sia come filesystem che come gestore volumen simile a LVM. Non è necessario quando si utilizza ZFS. Vedi la documentazione se vuoi saperne di più.

Notare la differenza tra ZFS e BTRFS. ZFS è più vecchio e più maturo, purtroppo solo sotto Solaris e OpenSolaris (purtroppo strangolato dall'oracolo). BTRFS è più giovane, ma l'ultima volta supportato molto bene. Raccomando kernel fresco. ZFS ha la deduplicazione online, che causa rallentamenti delle scritture, perché tutto è calcolato online. BTRFS supporta la dedupliazione off-line. Quindi questo salva le prestazioni, ma quando l'host non ha nulla a che fare, si esegue periodicamente lo strumento per effettuare la deduplicazione. E BTRFS è creato nativamente sotto Linux. Forse è meglio per te :)


1
Mi piace l' approccio di deduplicazione offline (o batch ) btrfs. Ottima discussione delle opzioni (compresa l' cp --reflinkopzione) qui: btrfs.wiki.kernel.org/index.php/Deduplication
Marcel Waldvogel

ZFS non è solo Solaris o OpenSolaris. È supportato nativamente in FreeBSD. Inoltre, ZFS su Linux è basato su driver di dispositivo; ZFS su FUSE è una cosa diversa.
KJ Seefried,

0

I collegamenti reali potrebbero non essere l'idea migliore; se un utente modifica il file, influisce su entrambi. Tuttavia, l'eliminazione di un collegamento reale non cancella entrambi i file. Inoltre, non sono del tutto sicuro se i collegamenti hardware occupino la stessa quantità di spazio (sul disco rigido, non sul sistema operativo) delle copie multiple dello stesso file; secondo Windows (con l'estensione Shell di collegamento), lo fanno. Certo, è Windows, non Unix ...

La mia soluzione sarebbe quella di creare un file "comune" in una cartella nascosta e sostituire i duplicati effettivi con collegamenti simbolici ... quindi, i collegamenti simbolici sarebbero incorporati con metadati o flussi di file alternativi che registra solo i due "file" sono diversi l'uno dall'altro, come se una persona volesse cambiare il nome del file o aggiungere copertine personalizzate o qualcos'altro del genere; potrebbe anche essere utile al di fuori delle applicazioni di database, come avere più versioni dello stesso gioco o software installato e testarle indipendentemente con anche le più piccole differenze.


0

Il modo più semplice è utilizzare il programma speciale dupeGuru

Screenshot delle preferenze di dupeGuru

come dice la documentazione

Opzioni di eliminazione

Queste opzioni influenzano il modo in cui avviene la cancellazione duplicata. Il più delle volte, non è necessario abilitarli.

Collega i file eliminati:

I file eliminati vengono sostituiti da un collegamento al file di riferimento. Puoi scegliere di sostituirlo con un collegamento simbolico o un collegamento reale. ... un collegamento simbolico è un collegamento al percorso del file. Se il file originale viene eliminato o spostato, il collegamento viene interrotto. Un hardlink è un collegamento al file stesso. Quel collegamento è buono come un file "reale". Solo quando tutti i collegamenti a un file vengono eliminati, il file stesso viene eliminato.

Su OSX e Linux, questa funzione è pienamente supportata, ma in Windows è un po 'complicata. Windows XP non lo supporta, ma Vista e versioni successive lo supportano. Tuttavia, affinché la funzione funzioni, dupeGuru deve funzionare con privilegi di amministratore.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.