2009-07-25 09:41:26 +0000 2009-07-25 09:41:26 +0000
104
104
Advertisement

Jak można zobaczyć rzeczywisty twardy link przez ls?

Advertisement

Uruchamiam

ln /a/A /b/B

Chciałbym zobaczyć w folderze a na jaki plik A wskazuje ls.

Advertisement
Advertisement

Odpowiedzi (9)

182
182
182
2009-07-25 10:01:32 +0000

Możesz znaleźć numer inode dla swojego pliku za pomocą

ls -i

a

ls -l

pokaże liczbę referencji (liczbę hardlinków do danego inode)

po znalezieniu numeru inode, możesz wyszukać wszystkie pliki z tym samym inode:

find . -inum NUM

pokaże nazwy plików dla inode NUM w aktualnym dir (.)

66
66
66
2009-07-25 09:51:57 +0000

Tak naprawdę nie ma dobrze zdefiniowanej odpowiedzi na twoje pytanie. W przeciwieństwie do symlinków, hardlinki są nie do odróżnienia od “oryginalnego pliku”.

Wpisy katalogowe składają się z nazwy pliku i wskaźnika do węzła inode. Inode z kolei zawiera metadane pliku i (wskaźniki do) rzeczywistej zawartości pliku). Utworzenie twardego dowiązania tworzy kolejną nazwę pliku + odniesienie do tego samego inode. Odniesienia te są jednokierunkowe (przynajmniej w typowych systemach plików) – inode przechowuje tylko liczbę odniesień. Nie ma wewnętrznego sposobu, aby dowiedzieć się, która jest “oryginalna” nazwa pliku.

Przy okazji, to właśnie dlatego wywołanie systemowe do “usunięcia” pliku nazywa się unlink. To tylko usuwa hardlink. Inode i dołączone do niego dane są usuwane tylko wtedy, gdy liczba odniesień do inode'a spadnie do 0.

Jedynym sposobem na znalezienie innych odniesień do danego inode'a jest wyczerpujące przeszukanie systemu plików sprawdzając, które pliki odnoszą się do danego inode'a. Możesz użyć ‘test A -ef B’ z powłoki, aby wykonać to sprawdzenie.

24
Advertisement
24
24
2009-07-25 10:01:38 +0000
Advertisement
ls -l

Pierwsza kolumna będzie reprezentować uprawnienia. Druga kolumna będzie liczbą podpozycji (dla katalogów) lub liczbą ścieżek do tych samych danych (twarde linki, w tym oryginalny plik) do pliku. Na przykład:

-rw-r--r--@ 2 [username] [group] [timestamp] HardLink
-rw-r--r--@ 2 [username] [group] [timestamp] Original
               ^ Number of hard links to the data
14
14
14
2013-08-15 08:52:16 +0000

Co powiesz na poniższy, prostszy sposób? (Ten ostatni może zastąpić długie skrypty powyżej!)

Jeśli masz konkretny plik <THEFILENAME> i chcesz znać wszystkie jego hardlinki rozrzucone po katalogu <TARGETDIR>, (który może być nawet całym systemem plików oznaczonym przez /)

find <TARGETDIR> -type f -samefile <THEFILENAME>

Rozszerzając logikę, jeśli chcesz znać wszystkie pliki w <SOURCEDIR> mające wiele hardlinków rozrzuconych po <TARGETDIR>:

find <SOURCEDIR> -type f -links +1 \
  -printf "\n\n %n HardLinks of file : %H/%f \n" \
  -exec find <TARGETDIR> -type f -samefile {} \;
```.
6
Advertisement
6
6
2015-04-21 19:32:47 +0000
Advertisement

Istnieje wiele odpowiedzi ze skryptami do znalezienia wszystkich hardlinków w systemie plików. Większość z nich robi głupie rzeczy, takie jak uruchamianie find, aby przeskanować cały system plików w poszukiwaniu -samefile dla KAŻDEGO pliku z wieloma powiązaniami. To jest szalone; wszystko czego potrzebujesz to sortowanie po numerze inode i drukowanie duplikatów.

Tylko jedno przejście przez system plików, aby znaleźć i pogrupować wszystkie zestawy plików z twardymi powiązaniami

find dirs -xdev \! -type d -links +1 -printf '%20D %20i %p\n' |
    sort -n | uniq -w 42 --all-repeated=separate

Jest to znacznie szybsze niż inne odpowiedzi dla znalezienia wielu zestawów plików z twardymi powiązaniami.
find /foo -samefile /bar jest doskonały dla tylko jednego pliku.

  • -xdev : ograniczenie do jednego systemu plików. Nie jest to konieczne, ponieważ wypisujemy również FS-id do uniq na
  • ! -type d odrzuć katalogi: wpisy . i .. oznaczają, że są zawsze połączone.
  • -links +1 : licznik linków ściśle > 1
  • -printf ... drukuj FS-id, numer inode i ścieżkę. (Z wypełnieniem do stałych szerokości kolumn, o których możemy powiedzieć uniq).
  • sort -n | uniq ... sortowanie numeryczne i uniquify na pierwszych 42 kolumnach, oddzielając grupy pustą linią

Użycie ! -type d -links +1 oznacza, że wejście sort jest tylko tak duże, jak końcowe wyjście uniq, więc nie wykonujemy dużej ilości sortowania łańcuchów. Chyba że uruchomisz go na podkatalogu, który zawiera tylko jeden z zestawu hardlinków. Tak czy inaczej, będzie to zużywać o wiele mniej czasu procesora na ponowne przemierzanie systemu plików niż jakiekolwiek inne opublikowane rozwiązanie.

przykładowe wyjście:

...
            2429 76732484 /home/peter/weird-filenames/test/.hiddendir/foo bar
            2429 76732484 /home/peter/weird-filenames/test.orig/.hiddendir/foo bar

            2430 17961006 /usr/bin/pkg-config.real
            2430 17961006 /usr/bin/x86_64-pc-linux-gnu-pkg-config

            2430 36646920 /usr/lib/i386-linux-gnu/dri/i915_dri.so
            2430 36646920 /usr/lib/i386-linux-gnu/dri/i965_dri.so
            2430 36646920 /usr/lib/i386-linux-gnu/dri/nouveau_vieux_dri.so
            2430 36646920 /usr/lib/i386-linux-gnu/dri/r200_dri.so
            2430 36646920 /usr/lib/i386-linux-gnu/dri/radeon_dri.so
...

TODO?: rozpakuj wyjście za pomocą awk lub cut. uniq ma bardzo ograniczoną obsługę wybierania pól, więc wyścielam wyjście find i używam stałej szerokości. 20 znaków jest wystarczająco szerokie dla maksymalnego możliwego numeru inode lub urządzenia (2^64-1 = 18446744073709551615). XFS wybiera numery inode na podstawie tego gdzie na dysku są alokowane, nie przylegająco od 0, więc duże systemy plików XFS mogą mieć 32-bitowe numery inode, nawet jeśli nie mają miliardów plików. Inne systemy plików mogą mieć 20-cyfrowe numery inode, nawet jeśli nie są gigantyczne.

TODO: posortuj grupy duplikatów według ścieżki. Sortowanie ich według punktu montowania, a następnie numeru inode powoduje mieszanie rzeczy razem, jeśli masz kilka różnych podkatalogów, które mają wiele hardlinków. (tj. grupy dup-grup idą razem, ale wyjście je miesza).

A końcowe sort -k 3 posortowałoby linie oddzielnie, a nie grupy linii jako pojedynczy rekord. Wstępne przetworzenie czegoś, co przekształci parę nowych linii w bajt NUL, i użycie GNU sort --zero-terminated -k 3 może załatwić sprawę. tr działa jednak tylko na pojedynczych znakach, nie na wzorcach 2- lub 1- 2. perl zrobi to (lub po prostu parsuje i sortuje w perlu lub awk). sed może również zadziałać.

3
3
3
2012-06-13 07:40:43 +0000

To jest w pewnym sensie komentarz do własnej odpowiedzi i skryptu Torocoro-Macho, ale oczywiście nie zmieści się w polu komentarza.


Przepisałem twój skrypt z bardziej prostymi sposobami na znalezienie informacji, a tym samym dużo mniej wywołań procesów.

#!/bin/sh
xPATH=$(readlink -f -- "${1}")
for xFILE in "${xPATH}"/*; do
    [-d "${xFILE}"] && continue
    [! -r "${xFILE}"] && printf '"%s" is not readable.\n' "${xFILE}" 1>&2 && continue
    nLINKS=$(stat -c%h "${xFILE}")
    if [${nLINKS} -gt 1]; then
        iNODE=$(stat -c%i "${xFILE}")
        xDEVICE=$(stat -c%m "${xFILE}")
        printf '\nItem: %s[%d] = %s\n' "${xDEVICE}" "${iNODE}" "${xFILE}";
        find "${xDEVICE}" -inum ${iNODE} -not -path "${xFILE}" -printf ' -> %p\n' 2>/dev/null
    fi
done

Starałem się zachować go tak podobnym do twojego, jak to tylko możliwe dla łatwego porównania.

Komentarze do tego skryptu i twojego

  • Zawsze należy unikać magii $IFS jeśli wystarczy glob, ponieważ jest to niepotrzebnie zagmatwane, a nazwy plików mogą zawierać nowe linie (ale w praktyce głównie z pierwszego powodu).

  • Powinieneś unikać ręcznego parsowania ls i tego typu danych wyjściowych tak bardzo jak to tylko możliwe, ponieważ prędzej czy później cię to ugryzie. Na przykład: w twojej pierwszej linii awk zawodzisz na wszystkich nazwach plików zawierających spacje.

  • printf często zaoszczędzi kłopotów, ponieważ jest tak solidny ze składnią %s. Daje też pełną kontrolę nad wyjściem i jest spójny we wszystkich systemach, w przeciwieństwie do echo.

  • stat może zaoszczędzić ci dużo logiki w tym przypadku.

  • GNU find jest potężny.

  • Twoje inwokacje head i tail mogły być obsługiwane bezpośrednio w awk za pomocą np. polecenia exit i/lub wyboru na zmiennej NR. Zaoszczędziłoby to wywołań procesów, co prawie zawsze poważnie poprawia wydajność w ciężko pracujących skryptach.

  • Twoje egrep mogą być równie dobrze po prostu grep.

2
Advertisement
2
2
2011-11-16 22:46:38 +0000
Advertisement

Bazując na skrypcie findhardlinks (zmieniłem jego nazwę na hard-links), oto co udało mi się przerobić i sprawić, że działa.

Wyjście:

# ./hard-links /root

Item: /[10145] = /root/.profile
    -> /proc/907/sched
    -> /<some-where>/.profile

Item: /[10144] = /root/.tested
    -> /proc/907/limits
    -> /<some-where else>/.bashrc
    -> /root/.testlnk

Item: /[10144] = /root/.testlnk
    -> /proc/907/limits
    -> /<another-place else>/.bashrc
    -> /root/.tested

 

# cat ./hard-links
#!/bin/bash
oIFS="${IFS}"; IFS=$'\n';
xPATH="${1}";
xFILES="`ls -al ${xPATH}|egrep "^-"|awk '{print $9}'`";
for xFILE in ${xFILES[@]}; do
  xITEM="${xPATH}/${xFILE}";
  if [[! -r "${xITEM}"]] ; then
    echo "Path: '${xITEM}' is not accessible! ";
  else
    nLINKS=$(ls -ld "${xITEM}" | awk '{print $2}')
    if [${nLINKS} -gt 1]; then
      iNODE=$(ls -id "${xITEM}" | awk '{print $1}' | head -1l)
      xDEVICE=$(df "${xITEM}" | tail -1l | awk '{print $6}')
      echo -e "\nItem: ${xDEVICE}[$iNODE] = ${xITEM}";
      find ${xDEVICE} -inum ${iNODE} 2>/dev/null|egrep -v "${xITEM}"|sed 's/^/ -> /';
    fi
  fi
done
IFS="${oIFS}"; echo "";
```.
1
1
1
2015-01-20 18:00:05 +0000

Rozwiązanie GUI naprawdę zbliża się do twojego pytania:

Nie można wyświetlić listy rzeczywistych plików z hardlinkami z “ls”, ponieważ, jak zauważyli poprzedni komentatorzy, “nazwy” plików są jedynie aliasami do tych samych danych. Jednakże, istnieje narzędzie GUI, które jest naprawdę bliskie temu, czego chcesz, a mianowicie wyświetla listę nazw plików, które wskazują na te same dane (jako hardlinki) w linuxie, nazywa się FSLint. Opcja, której potrzebujesz znajduje się pod “Name clashes” - odznacz “checkbox $PATH” w Search (XX) - i wybierz “Aliases” z rozwijanego pola po “for…” w kierunku górnego środka.

FSLint jest bardzo słabo udokumentowany, ale odkryłem, że upewniając się, że ograniczone drzewo katalogów w “Search path” z zaznaczonym checkboxem dla “Recurse?” i wyżej wymienionymi opcjami, lista twardo powiązanych danych ze ścieżkami i nazwami, które “wskazują” na te same dane są produkowane po przeszukiwaniu przez program.

1
Advertisement
1
1
2017-12-06 17:34:25 +0000
Advertisement

Można skonfigurować ls do podświetlania hardlinków za pomocą “aliasu”, ale jak już wspomniano wcześniej, nie ma sposobu na pokazanie “źródła” hardlinka, dlatego dołączam .hardlink, aby w tym pomóc.

Dodaj poniższe gdzieś w swoim .bashrc

alias ll='LC_COLLATE=C LS_COLORS="$LS_COLORS:mh=1;37" ls -lA --si --group-directories-first'
Advertisement

Pytania pokrewne

6
10
10
5
11
Advertisement
Advertisement