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ć mv
polecenie 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 f
na -not -type d
, patrz wyżej):
find -not -type d -links +1 -print0 | xargs -0 unhardlink.sh
cp -i
przełącznika, wypluł na mnie kilka wiadomości z pytaniem, czy powinien zastąpić./fileXXXXXX
($temp
plik), 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.unhardlink.sh
powinny 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.fuse
plików, może faktycznie zostać wysłanypath/to/hardlink-XXX
na inny fizyczny nośnik pamięci niżpath/to/original-file
, ale niewiele można na to poradzić.Odpowiedzi:
W skrypcie jest miejsce na ulepszenia, na przykład dodanie
-p
opcji docp
polecenia, 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.źródło
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-dereference
opcją.Coś jak:
(gdzie biec
ln foo/[12] bar
)Ze strony podręcznika:
źródło
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 :).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.