Jak mogę znaleźć wszystkie pliki dowiązane na stałe w systemie plików?

21

Potrzebuję znaleźć wszystkie dowiązane pliki w danym systemie plików. Np. Uzyskaj listę plików, każda linia zawiera połączone pary lub trojaczki itp.

Rozumiem mniej więcej, jak to zrobić, trzeba stworzyć słownik z kluczem i-węzła dla wszystkich plików / katalogów w systemie plików, z wyłączeniem „.” i „..” linki, a następnie indodes o więcej niż jednej nazwie to hardlinks… Ale mam nadzieję, że może istnieje gotowe rozwiązanie lub ktoś już napisał taki skrypt.

haimg
źródło

Odpowiedzi:

17

Możesz uruchomić następujące polecenie:

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

znaleźć wszystkie połączone pliki.

Lub wersja @mbafford:

find / -type f -links +1 -printf '%i %n %p\n'
Gilles Quenot
źródło
1
Dzięki, to nie jest dokładnie to, czego chciałem, ale wystarczająco blisko. Mogę dodać „% i”, aby wydrukować numery i-węzłów, a następnie posortować / pogrupować według niego ...
haimg,
15
Możesz uniknąć potrzeby awk, używając składni find-finds + n '. Np. Aby znaleźć wszystkie pliki z co najmniej dwoma linkami i wydrukować niezbędne informacje:find / -type f -links +1 -printf '%i %n %p\n'
mbafford
co powiesz na przepuszczanie sort(+ uniq)? Byłem ciekawy, więc spróbowałem na moim głównym komputerze (16 GB i5-2500k z ssd). z 2187757 plikami ( find / -xdev -type f | wc) zajmuje 12 rzeczywistych sekund po zwróceniu 3820 plików / 570 i-węzłów ( time sudo find / -xdev -type f -links +1 -printf "%i\n" | sort | uniq | wc). musisz uwzględnić %n %ppliki rzeczywiste, ponieważ wyjąłem je do zliczania i-węzłów.
north-bradley
17
find . -type f -links +1 2>/dev/null

daje listę wszystkich plików, które mają więcej niż jedno łącze, tzn. pliki, do których istnieje łącze twarde. Pętla nad tym jest wtedy stosunkowo łatwa - trudne rozwiązanie, jeśli nie masz tak wielu plików

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

Ale mam nadzieję, że są lepsze rozwiązania, na przykład pozwalając pierwszej findwybieranie numerów print-węzła, a następnie przy użyciu find„s -inumopcję, aby wyświetlić wszystkie pliki związane z tym węzła.

Klaudiusz
źródło
1
Auć! Spowoduje to ponowne skanowanie systemu plików w poszukiwaniu każdego
linku
1
Nie twierdziłem, że jest szybki - i to działa trochę dla małych drzew katalogowych. Oczywiście odpowiedni indeks, który można zbudować na przykład z danych wyjściowych find . -type f -printf '%i %p\n', pozwoliłby zbudować znacznie szybsze rozwiązanie.
Klaudiusz
I to nie obsługuje miejsca na ścieżce AFAIK.
Gilles Quenot,
W przypadku forpętli odpowiednie dostosowanie IFS działałoby. Aby przeanalizować dane wyjściowe polecenia find w moim komentarzu, powinno również działać zadeklarowanie wszystkiego między pierwszą spacją a końcem wiersza jako nazwą pliku.
Klaudiusz
1
@Sati: zapewnia odrzucenie komunikatów o błędach (np. W przypadku folderów, do których nie masz dostępu lost+founditp.); co jest szczególnie ważne, jeśli dane wyjściowe powinny być przetwarzane dalej, jak w drugim wierszu.
DJCrashdummy
1

IMHO najlepszym sposobem jest użycie następującego wiersza (na pewno musisz zastąpić to, /PATH/FOR/SEARCH/co chcesz wyszukać):

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

skanuje system plików tylko raz, pokazuje i-węzeł, liczbę dowiązań twardych i ścieżkę plików z więcej niż jednym dowiązaniem twardym i sortuje je według i-węzła.

jeśli denerwują Cię komunikaty o błędach dotyczące folderów, których nie możesz czytać, możesz rozwinąć linię do tego:

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
DJCrashdummy
źródło