Используя rdfind
Я нашел много жестко связанных файлов (~60-90) и хочу отменить связь со всеми ними. Одним из возможных решений является просто найти все файлы -link +1
и просто скопировать их, удалить и переместить обратно в имя ссылки.
Есть ли лучшее решение? Есть ли более простой способ сделать это?
решение1
Ты можешь сделать:
find . -type f -links +1 -exec sh -c '
{ rm -f "$1" && cat > "$1"; } < "$1"' sh {} \;
но это не сохранит метаданные файла. В Linux вы можете сделать вместо этого:
find . -type f -links +1 -exec sh -c '
{ rm -f "$1" && cp -p /proc/self/fd/0 "$1"; } < "$1"' sh {} \;
Обратите внимание, что если cat
/ или cp
не удастся (например, при переполнении диска), вы потеряете содержимое файла, которое cat
/ cp
не удалось скопировать.
Мы используем -exec {} \;
вместо -exec {} +
этого , чтобы счетчик ссылок файла обновлялся после того, как файл был найден, поэтому это find
не будетнаходитьпоследняя ссылка, если количество ссылок снизилось до 1 (что означает, что для файла с начальным количеством ссылок 4 будут перезаписаны только 3 экземпляра).
С помощью GNU tar
вы также можете сделать:
find . -type f -links +1 -print0 |
tar --hard-dereference --null -T - -cf - | tar xpf -
Это приведет к выполнению меньшего количества команд, но к перезаписи большего количества файлов.
Вы можете увидеть некоторые из них:
tar: ./file: file changed as we read it
для больших файлов, но это нормально, так как второй tar
отсоединит файл перед его перезаписью, так что по сути это будет очень похоже на первый подход. Просто первый tar
замечает уменьшение количества ссылок (и изменение ctime в результате), когда второй tar отсоединяет файл.