Come posso trovare tutti i file hardlinked su un filesystem?


21

Devo trovare tutti i file con collegamento fisico su un determinato filesystem. Ad esempio ottenere un elenco di file, ogni riga contiene coppie collegate o terzine, ecc.

Capisco più o meno come farlo, è necessario creare un dizionario codificato dall'inode per tutti i file / directory su un filesystem, escludere "." e ".." link, e quindi gli indode con più di un nome sono hardlink ... Ma spero che esista forse una soluzione già pronta, o che qualcuno abbia già scritto un tale script.

Risposte:


17

È possibile eseguire il comando seguente:

find / -type f -printf '%n %p\n' | awk '$1 > 1{$1="";print}'

per trovare tutti i file hard link.

O versione @mbafford:

find / -type f -links +1 -printf '%i %n %p\n'

1
Grazie, questo non è esattamente quello che volevo, ma abbastanza vicino. Posso aggiungere '% i' per stampare i numeri di inode e quindi ordinare / raggruppare per esso ...
haimg

15
Puoi evitare la necessità di awk usando "-link + n 'sintassi di find, ad es. Per trovare tutti i file con almeno due link e stampare le informazioni necessarie:find / -type f -links +1 -printf '%i %n %p\n'
mbafford,

che ne dite di passare attraverso sort(+ uniq)? ero curioso, quindi ho provato il mio computer principale (16 GB i5-2500k con SSD). con 2187757 file ( find / -xdev -type f | wc) richiede 12 secondi reali quando si restituiscono 3820 file / 570 inode ( time sudo find / -xdev -type f -links +1 -printf "%i\n" | sort | uniq | wc). dovresti includere il %n %pper i file effettivi come li ho estratti per il conteggio degli inode.
Northern-Bradley,

17
find . -type f -links +1 2>/dev/null

fornisce un elenco di tutti i file che hanno più di un collegamento, ovvero file a cui esiste un collegamento reale. Eseguire il ciclo su questo è quindi relativamente semplice: una soluzione caotica se non si dispone di così tanti file

for i in $(find . -type f -links +1 2>/dev/null); do find -samefile $i | awk '{printf "%s ", $1}'; printf "\n"; done | sort | uniq

Spero sinceramente che ci siano soluzioni migliori, ad esempio lasciando che la prima findchiamata stampi i numeri degli inode e quindi usando l find' -inumopzione per mostrare tutti i file associati a questo inode.


1
Ahia! Questo analizza il filesystem ancora e ancora per ogni file hardlinked ...
haim

1
Non ho affermato che fosse veloce - e in qualche modo funziona per piccoli alberi di directory. Naturalmente, un indice adeguato, che potrebbe essere creato, ad esempio, dall'output di find . -type f -printf '%i %p\n', consentirebbe di costruire una soluzione molto più veloce.
Claudio,

E questo non gestisce lo spazio nel percorso AFAIK.
Gilles Quenot,

Per il forloop, regolare IFS di conseguenza funzionerebbe. Per analizzare l'output del comando find nel mio commento, dichiarare che tutto il nome tra il primo spazio e la fine della riga dovrebbe essere anche il nome del file.
Claudio,

1
@Sati: assicura che i messaggi di errore vengano scartati (ad es. Per le cartelle a cui non hai accesso, lost+foundecc.); che è particolarmente importante, se l'output deve essere ulteriormente elaborato come nella seconda riga.
DJCrashdummy,

1

IMHO il modo migliore è usare la seguente riga (di sicuro devi sostituire /PATH/FOR/SEARCH/con quello che vuoi cercare):

find /PATH/FOR/SEARCH/ -xdev -printf '%i\t%n\t%p\n' | fgrep -f <(find . -xdev -printf '%i\n' | sort -n | uniq -d) | sort -n

questo esegue la scansione del filesystem una sola volta, mostra l'inode, il numero di hardlink e il percorso dei file con più di un hardlink e li ordina in base all'inode.

se sei infastidito dai messaggi di errore per le cartelle che non sei autorizzato a leggere, puoi espandere la riga in questo modo:

find /PATH/FOR/SEARCH/ -xdev -printf '%i\t%n\t%p\n' 2> /dev/null | fgrep -f <(find . -xdev -printf '%i\n' 2> /dev/null | sort -n | uniq -d) | sort -n
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.