У меня есть папка, которая содержит определенное количество файлов с жесткими ссылками (в той же папке или где-то еще), и я хочу де-хардлинкнуть эти файлы, чтобы они стали независимыми, и изменения в их содержимом не повлияют на другой файл (их количество ссылок становится равным 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
Таким образом, чтобы ООН-HardLink все жесткие ссылки ( Edit : изменен -type f
на -not -type d
, смотри выше):
find -not -type d -links +1 -print0 | xargs -0 unhardlink.sh
cp -i
переключателя, он высыпал на меня несколько сообщений, спрашивающих, должен ли он переопределить ./fileXXXXXX
( $temp
файл), даже если tmpfile должен давать уникальные имена файлов, поэтому необходимо быть какое-то состояние гонки или что-то еще, и с этим риск потерять некоторые данные.
unhardlink.sh
следует создать временный каталог внутри того же каталога, в котором содержится файл, который необходимо удалить из ссылки. В противном случае ваш рекурсивный вызов может произойти в другой файловой системе, и вы в конечном итоге переместите материал за границы файловой системы, потому что ваш временный каталог находится в текущем рабочем каталоге. Я думаю, вы могли бы передать "$(dirname "$i")/hardlink-XXXXXX"
в качестве аргумента mktemp вместо этого.
fuse
файловая система, она может на самом деле отправлять данные path/to/hardlink-XXX
на другой физический носитель информации path/to/original-file
, но с этим ничего не поделаешь.