Назад | Перейти на главную страницу

Разорвать все жесткие ссылки в папке

У меня есть папка, которая содержит определенное количество файлов с жесткими ссылками (в той же папке или где-то еще), и я хочу де-жестко связать эти файлы, чтобы они стали независимыми, и изменения их содержимого не повлияют на какие-либо другой файл (их количество ссылок становится равным 1).

Ниже я даю решение, которое в основном копирует каждую жесткую ссылку в другое место, а затем перемещает ее на место.

Однако этот метод кажется довольно грубым и подверженным ошибкам, поэтому я хотел бы знать, есть ли какая-нибудь команда, которая де-жестко связывает файл для меня.

Грубый ответ:

Найдите файлы с жесткими ссылками (редактировать: Чтобы также найти сокеты и т. Д., Которые имеют жесткие ссылки, используйте find -not -type d -links +1):

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

Грубый метод удаления жесткой связи с файлом (скопируйте его в другое место и переместите обратно): Редактировать: Как сказал Селада, лучше всего выполнить cp -p ниже, чтобы избежать потери временных меток и разрешений. Редактировать: Создайте временный каталог и скопируйте его в файл под ним, вместо того, чтобы перезаписывать временный файл, это минимизирует риск перезаписи некоторых данных, хотя mv команда по-прежнему рискованна (спасибо @Tobu). Редактировать: Попробуйте создать временный каталог в той же файловой системе (@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

Итак, чтобы снять жесткую ссылку со всех жестких ссылок (редактировать: изменено -type f к -not -type d, см. выше):

find -not -type d -links +1 -print0 | xargs -0 unhardlink.sh

В вашем сценарии есть возможности для улучшения, например, добавление -p вариант для cp , чтобы разрешения и временные метки сохранялись во время операции unhardlink, и вы могли бы добавить некоторую обработку ошибок, чтобы временный файл удалялся в случае ошибки, но основная идея вашего решения - единственная, которая будет работать. Чтобы отменить жесткую ссылку на файл, вы должны скопировать его, а затем переместить копию обратно на исходное имя. Не существует «менее грубого» решения, и у этого решения есть условия гонки на случай, если другой процесс одновременно обращается к файлу.

Если вы хотите сжечь дисковое пространство, и у вас есть относительно современная версия tar (например, что в Ubuntu 10.04 и CentOS 6), вы можете поиграть с --hard-dereference вариант.

Что-то вроде:

$ 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

(где я бежал 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

На странице руководства:

   --hard-dereference
          follow hard links; archive and dump the files they refer to