Чи є два файли з твердим посиланням?


27

Як я можу визначити, що два файли жорстко пов'язані з командного рядка? наприклад, щось пов’язує це:

$ ls
fileA fileB fileC

$ is-hardlinked fileA fileB
yes

$ is-hardlinked fileA fileC
no

Відповіді:


37

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

Ash, ksh, bash та zsh мають конструкцію, яка робить для вас перевірку: оператор рівності файлів -ef.

[ fileA -ef fileB ] && ! [ fileA -ef fileC ]

У більш складних випадках ls -i /path/to/fileперераховується номер inode файла. df -P /path/to/fileпоказує, на якій файловій системі знаходиться файл (якщо два файли в одному каталозі, вони знаходяться в одній файловій системі). Якщо ваша система має statкоманду, вона, ймовірно, може відображати номери inode та файлової системи ( statзалежить від системи до системи, перевірте свою документацію). Якщо ви хочете швидкий огляд жорстких посилань всередині каталогу, спробуйте ls -i | sort(можливо, перекладіть на пробудження )

¹ Усі рідні файлові системи Unix та декілька інших, таких як NTFS, але, можливо, не екзотичні випадки, такі як CramFS.


І, безумовно, не на чомусь на базі FAT, де це було б виявлено як "зшитий" файл.
Ігнасіо Васкес-Абрамс

4
Зауважте, що fileA -ef fileBтакож повертається 0(успіх), якщо fileAце посилання на fileB, або навпаки, або вони обидва посилаються на один і той же файл.
janmoesen

як ви насправді виконуєте запропоновану вами команду? Я спробував [.bashrc -ef .bash / .bashrc] і варіанти цього, але він насправді не спрацював.
Чарлі Паркер

@CharlieParker [ .bashrc -ef .bash/.bashrc ]правильний. Без контексту, звичайно, я не маю уявлення, чому це "насправді не працювало" - ви могли б порівнювати неправильні файли, ви не можете перевірити результат правильно, ви можете використовувати оболонку без -ef,
Жилль "ТАК - перестаньте бути зла"

2
@CharlieParker Команда є фактично [і є синонімом test. Але man [або man testви отримаєте сторінку man із зовнішньої команди, тоді як майже в кожній оболонці є вбудована команда з дещо іншими параметрами, тому вам потрібно переглянути цю інструкцію в посібнику з оболонки.
Жил 'ТАК - перестань бути злим'

4
function is-hardlinked() {
    r=yes
    [ "`stat -c '%i' $1`" != "`stat -c '%i' $2`" ] && r=no
    echo $r
}

6
Зауважте, що це може бути помилковим позитивом, якщо два файли є в різних файлових системах, але, мабуть, мають однаковий inode. Вам також потрібно перевірити номер пристрою ( stat -c %d). І якщо ви працюєте в Linux (з урахуванням вашої statкоманди), ваша оболонка має [ fileA -ef fileB ]все це зробити безпосередньо. Крім того, ваша команда безперешкодно розбивається з іменами файлів, що містять пробіли або \[?*, або починається з -: завжди ставити подвійні лапки навколо командних підданих ( "$(stat -c %i -- "$1")").
Жил "ТАК - перестань бути злим"

1
Чому б ви використовували купу громіздких, але портативних конструкцій, а потім нерентабельне functionключове слово з ім'ям функції, яке (за рахунок того, що містить тире) порушує конвенції POSIX щодо дозволених імен?
Чарльз Даффі

Ви забули процитувати своє $1і $2. Ви також можете використовувати $()синтаксис замість зворотних посилань, оскільки дужки чітко пояснюють, звідки починається команда та де вона закінчується, а гніздування простіше.
Джош

3

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

stat -c '%i' fileA fileB fileC

4
Цього недостатньо: ви отримаєте однакове число для двох файлів, якщо вони знаходяться в різних файлових системах, але вони мають однаковий inode. Вам також потрібно перевірити номер пристрою ( stat -c %d). І якщо ви працюєте в Linux (з урахуванням вашої statкоманди), ваша оболонка має [ fileA -ef fileB ]все це зробити безпосередньо.
Жил "ТАК - перестань бути злим"

0

З GNU find(1)версії 4.2.11 або новішої ви також можете використовувати це:

if [ "yes" = "$(find fileA -samefile fileB -exec echo yes \;)" ]; then
    echo yes
else
    echo no
fi

Якщо fileAфайл є тим самим, що і fileBтоді, findбуде надруковано "так", і умова стане справжньою.

На відміну від використання оператора рівності файлів, -efце породжує новий процес.

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