Порушення жорсткої зв'язку на місці?


13

Я тримаю свої дотфіли під контролем версій, і сценарій, що розгортає їх, створює жорсткі посилання. Я також використовую, etckeeperщоб поставити /etcпід контроль версій. Нещодавно я отримав такі попередження:

warning: hard-linked files could cause problems with bzr

Проста копія ( cp filename.ext filename.ext) не працюватиме:

cp: `filename.ext' and `filename.ext' are the same file

Перейменування / переміщення файлу - за винятком томів - також не порушує жорстке посилання.

Отже, моє запитання: чи є спосіб розірвати жорстке посилання на файл, фактично не знаючи, де знаходиться інша жорстка посилання / файли до цього файлу?


2
Команда "rm" перериває жорсткі посилання.
Йохан

Відповіді:


14
cp -p filename filename.tmp
mv -f filename.tmp filename

Зробити це сценарієм:

dir=$(dirname -- "$filename")
tmp=$(TMPDIR=$dir mktemp)
cp -p -- "$filename" "$tmp"
mv -f -- "$tmp" "$filename"

Зробити копію спочатку, а потім перемістити її на місце, має перевагу те, що файл атомно змінюється від жорсткого посилання до окремої копії (немає моменту, коли filenameвона часткова або відсутня).


7

Ви, мабуть, маєте на увазі, що хочете розділити жорстке посилання на окремий незалежний файл.

mv hardlink tempname && cp tempname hardlink && rm tempname

Жорстке посилання - це з'єднання між записом у каталозі та блоком inode на диску.

inodes зберігає метадані файлів, а для невеликих файлів деякі файлові системи зберігають дані в inode, інакше вказують на блоки даних, а для дуже великих файлів - непрямі та подвійні непрямі списки покажчиків на одиниці розподілу диска.

Незважаючи на те, з'єднання між назвою файлу (Що і створює команда ls) та блоком inode, який зберігає ці метадані, називається жорстким зв’язком.

Наявність декількох жорстких посилань на один файл означає той самий інод, на який посилається більше одного запису каталогу, можливо, в різних каталогах (в одній файловій системі)

rm видаляє запис імені файлу з каталогу. Після того, як на inode більше не посилаються жодні файли, його простір звільняється для використання іншими файлами.


Справді. Ось що мав на увазі cpі mvприклади. Тому я не бачу використання тимчасового файлу.
0xC0000022L

@ 0xC0000022L, Ні, вклади не містять покажчиків на інші входи. Просто до блоків даних (або вони можуть подвоїтись як простір даних, якщо об’єкт малий).
vonbrand

4
Переконайтеся, що права доступу та інші дані зберігаються під час копіювання, тобто. використання cp -a(принаймні GNU coreutils).
vonbrand

@ 0xC0000022L, якщо уважно подивитися, для початкового файлу є лише тимчасове ім’я, новий файл створюється лише на останньому кроці.
vonbrand

@vonbrand Вони дійсно можуть залежно від того, яка файлова система використовується.
Йохан

4

Помістіть це в кінці файлу ~ / .bashrc.

delink () { tmpfile="$1$(date)"; cp -a "$1" "$tmpfile"; mv "$tmpfile" "$1"; }

Запустити так

delink filename

3

Найкращий спосіб зробити це за допомогою bash-скрипту:

if [ -f "$1" ] ; then
dir="$(dirname -- "$1")"
tmpfile="$(mktemp --tmpdir="$dir")"
cp --preserve=all -f -- "$1" "$tmpfile"
mv -f -- "$tmpfile" "$1"
fi

пункти до зауваження:

  • перевірте, чи є звичайним файлом, перш ніж спробувати скопіювати його
  • тримайте старий файл на місці, поки копія не буде готова
  • використовувати mktempдля створення файлу, який гарантовано не існує
  • використовувати -fдля примусового перезапису та --preserve=allзбереження метаданих максимально схожих на вихідний файл
  • використовувати --та "цитувати шляхи, що містять пробіли та / або починаючи з-

Зробити заміну без створення тимчасового файлу неможливо при поточних (3.16) системних викликах Linux: в той час як можна атомно перезаписати файл (тобто видалити старий файл і замінити на новий в якості однієї операції), він це неможливо зробити з файлом, який не має імені у файловій системі (тобто тимчасовий файл, створений за допомогою O_TMPFILEпрапора openфункції), оскільки renameфункція вимагає ім'я файлу як вхідного (не існує версія, renameяка б вводила дескриптор файлу - див. подробиці тут )


1
Зауважте, що вам не вдалося процитувати це ім’я у своїх dirnameта mktempдзвінках Виправлено це для вас ...
derobert

@derobert о, дякую, але це не буде працювати, оскільки є вкладені подвійні лапки ... потрібно ще виправити! Kinda hate bash
pqnet

3
Він працюватиме через $( ... )заміну команди -style. Однією з причин його приємніше, ніж ` ... `-стиль.
дероберт

@derobert приємно, не знав цього. Крім того, як можна використовувати `внутрішні теги коду?
pqnet

Ви можете врятуватися від них за допомогою нахилів. Отож, щоб `вас ввели: `\``(звичайно, я подвійно уникав цього, щоб показати, що ви вводите).
дероберт

-1

Команда, яку ви шукаєте, - це unlink


Можливо, моє запитання було не ясним, але "на місці" та на прикладах із, cpі mvя мав намір дати зрозуміти, що хочу, щоб файл існував після цього.
0xC0000022L

Ах, я не вважав цього зрозумілим, ні. Тоді ви повинні піти з відповіддю Йохана.
Дженні Д

1
Команда "від’єднати" просто видаляє файл (що робить системний виклик unlink ()).
Рауль Салінас-Монтеагудо

-1

Якщо ви шукаєте всі назви файлів, які є твердим посиланням на цей файл, ви можете використовувати:

find -samefile myknowhardlinkfile

також ls -il myknowhardlinkfileпокаже вам кількість імен файлів, жорстке посилання на той самий inode (третє поле).

101612442 -rw-rw-r--. 2 me me 0 Aug  5 07:07 myknowhardlinkfile

Це насправді не відповідає на питання, хоча може бути корисним.
Flimm
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.