У меня есть папка, которая содержит определенное количество файлов с жесткими ссылками (в той же папке или где-то еще), и я хочу де-жестко связать эти файлы, чтобы они стали независимыми, и изменения их содержимого не повлияют на какие-либо другой файл (их количество ссылок становится равным 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