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