Визначення того, чи файл є твердим або символічним посиланням?


51

Я створюю скрипт оболонки, який би переніс назву / шлях до файлу і визначив, чи файл є символічним або жорстким посиланням.

Єдине, я не знаю, як зрозуміти, чи є вони жорсткою ланкою. Я створив 2 файли, одне тверде посилання та одне символічне посилання для використання в якості тестового файлу. Але як я можу визначити, чи файл є твердим посиланням або символічним у скрипті оболонки?

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


16
Що ви маєте на увазі під твердим посиланням? Усі файли - це жорсткі посилання.
terdon

1
@terdon ln /foo/bar/ /foo/bar2робить жорстке ln -s /foo/bar /foo/bar2посилання, а робить симпосилання , ось що він має на увазі?
DisplayName

14
@DisplayName так, але всі файли є посиланнями на їхній inode. Ось так працюють файлові системи Linux. У вашому прикладі bar2і barобидва жорсткі посилання, просто вказують на один і той же індед.
тердон

10
@DisplayName так, вони є жорсткими посиланнями на інші входи . Тут немає суперечності. Файл - посилання на inode. Це визначення файлу. У вашому випадку ви маєте ці посилання в різних місцях, але це не змінює базову структуру даних. Моя думка, що і те, barі інше bar2є однаково важливим. Одне не є посиланням на інше, вони обидва посилання, але вказують на один і той же індед.
terdon

3
@Scott ні, я кажу, що звичайні файли є жорсткими посиланнями і що жорсткі посилання, створені lnне відрізняються від звичайних файлів.
terdon

Відповіді:


42

Відповідь Джима пояснює, як перевірити наявність симпосилання: за допомогою тесту test's -L.

Але тестування на "жорстке посилання" - це, ну, строго кажучи, не те, що ти хочеш. Жорсткі посилання працюють через те, як Unix обробляє файли: кожен файл представлений одним inode. Тоді в одному inode є нуль або більше імен або записів каталогів або, технічно, жорсткі посилання (те, що ви називаєте "файл").

На щастя, statкоманда, де вона доступна, може сказати вам, скільки імен має Inode.

Отже, ви шукаєте щось подібне (тут передбачається реалізація GNU або busybox stat):

if [ "$(stat -c %h -- "$file")" -gt 1 ]; then
    echo "File has more than one name."
fi

-c '%h'Біт говорить statтільки виводити кількість жорстких посилань на індексний дескриптор, тобто, кількість імен файл має. -gt 1потім перевіряє, якщо це більше 1.

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


ОК, просто щоб було зрозуміло, я можу вивести кількість жорстких посилань у файлі, використовуючи команду stat, і якщо його більше, ніж 1, то у нього є інший файл, пов'язаний десь на розділі.
k-Rocker

@ k-Rocker Так. Тоді воно має другу назву десь на перегородці.
дероберт

1
В ОС X або * BSD це так stat -f %l /path/to/file. Ви також можете використовувати, gstat -c %h /path/to/fileякщо у вас встановлені GNU coreutils без їхніх імен за замовчуванням (з Homebrew в OS X).
ВВП2

29

Приклад:

$ touch f1
$ ln f1 f2
$ ln f1 f3
$ ln -s f1 s1
$ ln -s f2 s2
$ ln -s ./././f3 s3
$ ln -s s3 s4
$ ln s4 s5
$ ls -li
total 0
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 f1
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 f2
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 f3
10802345 lrwxrwxrwx 1 stephane stephane 2 Nov 12 19:56 s1 -> f1
10802346 lrwxrwxrwx 1 stephane stephane 2 Nov 12 19:56 s2 -> f2
10802347 lrwxrwxrwx 1 stephane stephane 8 Nov 12 19:56 s3 -> ./././f3
10802384 lrwxrwxrwx 2 stephane stephane 2 Nov 12 19:56 s4 -> s3
10802384 lrwxrwxrwx 2 stephane stephane 2 Nov 12 19:56 s5 -> s3

В f1, f2і f3запис каталогу і той же файл (той же індексний дескриптор: 10802124, ви помітите , кількість посилань є 3). Вони є жорсткими посиланнями на той самий звичайний файл.

s4і s5також є тим самим файлом (10802384). Вони типу симпосилання , не регулярні . Вони вказують на шлях, тут s3. Оскільки s4і s5є записами одного і того ж каталогу, цей відносний шлях s3вказує на той самий файл (той, який має inod 10802347) для обох.

Якщо ви це зробите ls -Ll, це запит отримати інформацію про файл після вирішення символьних посилань:

$ ls -lLi
total 0
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 f1
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 f2
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 f3
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 s1
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 s2
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 s3
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 s4
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 s5

Ви знайдете, що всі вони відповідають одному файлу (10802124).

Ви можете перевірити, чи файл є символьним посиланням [ -L file ]. Так само ви можете перевірити, чи файл є звичайним файлом [ -f file ], але в цьому випадку перевірка робиться після вирішення символьних посилань.

жорсткі посилання - це не тип файлу, вони просто різні назви файлу (будь-якого типу).


19

Використання команди -hта -Lоператорів testкоманди:

-h file 
true if file is a symbolic link

-L file 
true if file is a symbolic link

http://www.mkssoftware.com/docs/man1/test.1.asp

Відповідно до цієї нитки SO вони мають однакову поведінку, але -Lє кращою.


гаразд круто, а як бути з жорсткими посиланнями? Я перевірив протектор, але нічого про жорсткі посилання. Якщо -L повертає помилкове, чи означає це тверде посилання? чи просто звичайний файл?
k-Rocker

1
Жорсткі посилання поділяють те саме inode. Крім того, м'які посилання показують lна початку його ls -lвиводу ... Я думаю, що ви, можливо, зможете скласти ці правила разом у сценарій, плюс [[ -L file ]]тест, щоб побачити, чи даний файл м'який чи жорсткий .
jimm-cl

Ок, також, як я можу знайти розділ призначення символічного посилання?
k-Rocker

3

Тут є дуже багато правильних відповідей, але я не думаю, що ніхто насправді вирішив оригінальну помилку. Початкове запитання в основному "коли я створюю символічне посилання, його легко визначити згодом. Але я не можу зрозуміти, як визначити жорстке посилання". І так, відповіді в основному зводяться до "ти не можеш", і більш-менш пояснюємо чому, але, схоже, ніхто не визнав, що це, справді, це заплутано і дивно.

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

Насправді дуже коротка відповідь полягає в тому, що жорстке посилання насправді зовсім не посилання, не так, як символічне посилання. Це новий запис у структурі каталогів, який вказує на ту саму купу байтів, що і оригінальна запис каталогу, і коли ви створили її, вона є такою ж «реальною» і законною, як і перша. Кожен "звичайний" файл на вашому диску має щонайменше одне тверде посилання; без цього ви його не побачили ні в якомукаталог і не зможе посилатися на нього чи використовувати його. Отже, якщо у вас є файл Fred.txt, і ви жорстко посилаєтеся на нього Wilma.txt і Barney.txt, усі три імені (та записи каталогів) посилаються на один і той же файл, і всі вони однаково дійсні. В ОС немає жодного способу сказати, що одна з записів була створена при натисканні кнопки "Зберегти" у текстовому редакторі, а інші зроблені за допомогою команди "ln".

ОС дійсно повинні відстежувати , скільки різних записів , що вказують на той же файл, хоча. Якщо ви видалите Wilma.txt, не дивно, що ви не звільняєте місця на диску. Але якщо ви видалите Fred.txt ("оригінальний" файл), ви все одно не будете звільняти місця на диску, тому що дані на диску, відомі як Fred.txt, все ще є Barney.txt. Тільки коли ви видалите всі записи каталогів, ОС буде виділяти простір, який займали самі дані.

Якщо Barney.txt була символічною посиланням, то видалення Fred.txt б уже де-виділено простір, і Barney.txt тепер буде сломанной посиланням. Крім того, якщо ви перемістите або перейменуєте файл, на якому вказується символічне посилання, ви перервете посилання. Але ви можете переміщувати або перейменовувати жорсткий зв'язаний файл все, що вам потрібно, не порушуючи інші записи каталогів, які вказують на цей файл / дані, оскільки всі вони - записи каталогів, що посилаються на той самий блок даних на диску (за допомогою inode # цих даних).

[Це через два роки, і цей останній шматочок збентежив мене на хвилину, тому, я думаю, я уточню. Якщо ви введете "mv ./Wilma.txt ../elsewhere/Betty.txt", схоже, ви переміщуєте файл, але насправді це не так. Те, що ви насправді робите, - це вилучення позиції зі списку каталогів у вашому поточному каталозі, тому що "ім'я" Wilma.txt "пов'язане з даними, які можна знайти за допомогою inode ###### #, "та додавання нової позиції до списку каталогів ../elsewhere, де написано" ім'я "Betty.txt" пов'язано з даними, які можна знайти за допомогою inode ####### ". Ось чому ви можете «перемістити» 2-гігабайтний файл так само швидко, як і 2-кілобайтний файл, доки ви переміщуєте їх в інше місце на тому самому диску.]

Оскільки ОС повинна відслідковувати, скільки різних записів каталогів вказують на один і той же фрагмент даних, ви можете сказати, чи певний файл був жорстко пов’язаний, хоча ви не можете точно сказати, чи вводиться каталог, який ви "дивишся на" оригінальний "той чи ні. Один із способів - команда "ls", зокрема "ls -l" (це малі регістри після тире)

Позичити попередній приклад….

 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 f1

Перший лист є тире, тому це не каталог або щось інше екзотичне, це "звичайний" звичайний файл. Але якби це було по-справжньому звичайним, це число після частини rwx-ish було б "1", як і в ", є одна запис каталогу, що вказує на цей блок даних". Але це частина демонстрації жорстких посилань, тож натомість вона каже "3".

Зауважте, що це, можливо, може призвести до дивної та загадкової поведінки (якщо ви ще не обмотали голову навколо жорстких посилань, тобто). Якщо ви відкриєте Fred.txt у своєму текстовому редакторі та внесете деякі зміни, чи побачите ви однакові зміни у Wilma.txt та Barney.txt? Може бути. Мабуть. Якщо ваш текстовий редактор зберігає зміни, відкриваючи оригінальний файл і записуючи зміни до нього, то так, усі три назви все одно будуть вказувати на той самий (щойно змінений) текст. Але якщо ваш текстовий редактор створить новий файл (Fred-new-temp.txt), запише до нього змінену версію, видалить Fred.txt, а потім перейменує Fred-new-temp.txt у Fred.txt, Wilma та Barney як і раніше вказувати на оригінальну версію, а не на нову змінену версію. Якщо ви не розумієте жорстких посилань, це може звести вас з розуму. :) [Гаразд, я насправді особисто нікого не знаютекстові редактори, які б робили новий файл / перейменувати річ, але я знаю багато інших програм, які роблять саме це, тому будьте уважні.]

Підсумкове зауваження: одна з речей, на яку перевіряється "fsck" (перевірка файлової системи), - це наявність на вашому диску блоків даних, які якимось чином більше не посилаються на жодні записи каталогів. Іноді щось йде не так, і єдиний запис каталогу, який вказує на inode, видаляється, але сам простір диска не позначається як "доступний". Отже, одним із завдань fsck є зіставлення всього виділеного простору з усіма записами каталогу, щоб переконатися у відсутності неподілених файлів. Якщо він знаходить деякі, він створює нові записи каталогів і ставить їх у "втрачено + знайдено".


Просто цікаво, що це за "інші програми, які роблять саме так"?
phk

@phk Не знаю, про що він конкретно думає, але це досить поширений підхід для виконання дій, які можуть зайняти багато часу і, якщо не вдасться, залишать вас у невизначеному стані. Наприклад, якщо ви намагаєтеся завантажити з віддаленого сервера, і ви знаєте, що існує ймовірність, що сервер може затримати час, тоді одним із підходів було б завантажити весь вміст у тимчасовий файл. Таким чином, якщо щось завантажується з завантаженням, у вас все ще є оригінальний файл.
cwallenpoole

Єдиною програмою, яку я знаю напевно, є FreeHand, оскільки якщо / коли вона виходить з ладу під час збереження, позаду залишається тимчасовий файл, а не зіпсований оригінальний файл. Але я бачив і інші програми, які роблять це; Наразі я не можу навести конкретні приклади.
Снарке

2

ви можете використовувати readlink FILE; echo $?. Це повертає 1, коли це тверде посилання, і 0, коли це симпосилання.

На вхідній сторінці: "Якщо викликається посиланням для читання, друкується лише ціль символічного посилання. Якщо дана аргументація не є символічним посиланням, readlink нічого не надрукує та вийде з помилкою".

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