Przerwij wszystkie twarde linki w folderze

10

Mam folder, który zawiera pewną liczbę plików, które mają twarde linki (w tym samym folderze lub gdzie indziej), i chcę usunąć link do tych plików, aby stały się niezależne, a zmiany ich zawartości nie wpłyną na żadne inny plik (liczba linków zmienia się na 1).

Poniżej podaję rozwiązanie, które zasadniczo kopiuje każdy twardy link do innej lokalizacji, a następnie przenosi go z powrotem na miejsce.

Jednak ta metoda wydaje się dość prymitywna i podatna na błędy, więc chciałbym wiedzieć, czy istnieje jakieś polecenie, które usunie dla mnie link do pliku.

Surowa odpowiedź:

Znajdź pliki z twardymi linkami ( Edytuj : Aby również znaleźć gniazda itp., Które mają twarde linki , użyj find -not -type d -links +1):

find      -type f -links +1 # files only
find -not -type d -links +1 # files, sockets etc.

Prymitywna metoda usunięcia twardego linku z pliku (skopiuj go do innej lokalizacji i przenieś go z powrotem): Edytuj: Jak powiedziała Celada, najlepiej wykonać cp -p poniżej, aby uniknąć utraty znaczników czasu i uprawnień. Edycja: Utwórz katalog tymczasowy i skopiuj do pliku znajdującego się pod nim, zamiast nadpisywać plik tymczasowy, minimalizuje to ryzyko nadpisania niektórych danych, choć mvpolecenie jest nadal ryzykowne (dzięki @Tobu). Edycja: Spróbuj utworzyć katalog tymczasowy w tym samym systemie plików (@MikkoRantalainen).

# This is unhardlink.sh
set -e
for i in "$@"; do
  temp="$(mktemp -d -- "${i%/*}/hardlnk-XXXXXXXX")"
  [ -e "$temp" ] && cp -ip "$i" "$temp/tempcopy" && mv "$temp/tempcopy" "$i" && rmdir "$temp"
done

Tak więc, aby cofnąć hardlink wszystkich twardych linków ( Edytuj : zmieniono -type fna -not -type d, patrz wyżej):

find -not -type d -links +1 -print0 | xargs -0 unhardlink.sh
Suzanne Dupéron
źródło
Nie uważałbym tego za „prymitywne”. Jedynym sposobem, aby uzyskać to szybciej, jest prawdopodobnie wykonanie pewnej sztuczki przy wywołaniu systemowym sendfile () oraz odłączenie pliku open source i przepisanie celu w miejscu. Szczerze mówiąc, nie jest to warte wysiłku.
Matthew Ife
Przez „surowe” mam na myśli to, że na przykład, kiedy uruchomiłem to polecenie za pomocą cp -iprzełącznika, wypluł na mnie kilka wiadomości z pytaniem, czy powinien zastąpić ./fileXXXXXX( $tempplik), mimo że plik tmp powinien podać unikalne nazwy plików, więc musi być czymś w rodzaju wyścigu lub czymkolwiek, a wraz z nim ryzyko utraty niektórych danych.
Suzanne Dupéron
1
To normalne, że plik istnieje, właśnie utworzyłeś go przy pomocy tempfile (nb: przestarzałe na rzecz mktemp, ale nie to spowodowało twój problem).
Tobu
1
Twoja unhardlink.shpowinny stworzyć katalog tymczasowy wewnątrz tego samego katalogu, który zawiera plik, który należy unhardlinked. W przeciwnym razie wywołanie rekurencyjne może się powtórzyć w innym systemie plików, co może spowodować przeniesienie elementów poza granice systemu plików, ponieważ katalog tymczasowy znajduje się w bieżącym katalogu roboczym. Myślę, że "$(dirname "$i")/hardlink-XXXXXX"zamiast tego możesz podać argument jako argument dla mktemp.
Mikko Rantalainen
1
@MikkoRantalainen Bardzo dziękuję, zaktualizowano! Zauważ, że jeśli system plików jest jakimś związkiem lub systemem fuseplików, może faktycznie zostać wysłany path/to/hardlink-XXXna inny fizyczny nośnik pamięci niż path/to/original-file, ale niewiele można na to poradzić.
Suzanne Dupéron

Odpowiedzi:

9

W skrypcie jest miejsce na ulepszenia, na przykład dodanie -popcji do cppolecenia, dzięki czemu uprawnienia i znaczniki czasu zostaną zachowane podczas operacji odhaczania łącza, a można dodać obsługę błędów, aby plik tymczasowy został usunięty w przypadku błędu, ale podstawowa idea Twojego rozwiązania jest jedyna, która zadziała. Aby usunąć link do pliku, musisz go skopiować, a następnie przenieść kopię z powrotem do oryginalnej nazwy. Nie ma „mniej surowego” rozwiązania, które ma warunki wyścigu na wypadek, gdyby inny proces uzyskiwał dostęp do pliku w tym samym czasie.

Celada
źródło
Rzeczywiście, zawsze używam cp -a podczas kopiowania rzeczy, aby zachować wszystko, ponownie tworzyć i kopiować dowiązania symboliczne jako dowiązania symboliczne. Nie wiem, dlaczego tym razem zapomniałem, ale po zobaczeniu twojej odpowiedzi zrozumiałem, że zepsułem wszystkie moje znaczniki czasu i musiałem (raczej boleśnie) odzyskać je z kopii zapasowej.
Suzanne Dupéron,
5

Jeśli chcesz spalić miejsce na dysku i masz stosunkowo nowoczesną wersję tar(np. Tego, co jest na Ubuntu 10.04 i CentOS 6), możesz grać z tą --hard-dereferenceopcją.

Coś jak:

$ cd /path/to/directory
$ ls -l *
bar:
total 12
-rw-rw-r-- 2 cjc cjc 2 May  6 19:07 1
-rw-rw-r-- 2 cjc cjc 2 May  6 19:07 2
-rw-rw-r-- 1 cjc cjc 2 May  6 19:07 3

foo:
total 12
-rw-rw-r-- 2 cjc cjc 3 May  6 19:07 1
-rw-rw-r-- 2 cjc cjc 2 May  6 19:07 2
-rw-rw-r-- 1 cjc cjc 2 May  6 19:07 4

(gdzie biec ln foo/[12] bar)

$ tar cvf /tmp/dereferencing.tar --hard-dereference .
$ tar xvf /tmp/dereferencing.tar
$ ls -l *
bar:
total 12
-rw-rw-r-- 1 cjc cjc 2 May  6 19:07 1
-rw-rw-r-- 1 cjc cjc 2 May  6 19:07 2
-rw-rw-r-- 1 cjc cjc 2 May  6 19:07 3

foo:
total 12
-rw-rw-r-- 1 cjc cjc 3 May  6 19:07 1
-rw-rw-r-- 1 cjc cjc 2 May  6 19:07 2
-rw-rw-r-- 1 cjc cjc 2 May  6 19:07 4

Ze strony podręcznika:

   --hard-dereference
          follow hard links; archive and dump the files they refer to
cjc
źródło
Podejrzewam, że niewiele smoły nie da rady. Niezła poprawka.
Joseph Kern
Zapomniałem wspomnieć, że nie mam wystarczającej ilości miejsca na dysku, aby wszystko skopiować. Zasadniczo twoja metoda jest taka sama cp -a --no-preserve=links /path/to/folder /path/to/copy && rm -rf /path/to/folder && mv /path/to/copy /path/to/folder, jeśli się nie mylę. Sądzę jednak, że twoja metoda byłaby bardziej wydajna, ponieważ tar wymagałby mniejszej liczby operacji na dysku, a więc mniej kłopotów. To samo można osiągnąć za pomocą rsync, z jeszcze niższą wydajnością niż metoda cp :).
Suzanne Dupéron,
1
Aby uniknąć używania dużej ilości dodatkowego dysku, może być możliwe uruchomienie czegoś takiego, tar cvf - --hard-dereference . | tar xf -ale może istnieć sytuacja wyścigu, która spowoduje wybuch rzeczy. Nie próbowałem tego i jestem w tej chwili trochę niechętny.
cjc