Сравните символическую ссылку и ее цель с помощью bash test -ef

TL;DR: почему [ symlink_to_file_a -ef file_a ] возвращает true?


Мне нужно проверить, является ли файл b (в основном символическая ссылка) тем же, что и файл a, чтобы попытаться узнать, являются ли a и b жестко связаны друг с другом и жестко свяжут их, если это не так.
Я использую условное выражение -ef и руководство по bash говорит:

файл1 -ef файл2
Истинно, если файл1 и файл2 относятся к одному и тому же устройству и номерам инодов.

Я сравниваю только символическую ссылку/обычный файл, и индексные дескрипторы a и b разные, но результат True.

Ответ на аналогичный вопрос гласит:

Если да, то будет ли номер инода одинаковым для цели и ссылок?

Нет. Обычно символическая ссылка представляет собой файл со своим индексным узлом (с типом файла, собственными блоками данных и т. д.)

Я не уверен в том, что я понял, но я мог найти некоторые пояснения по этому поводу в спецификация ext4 :

Цель символической ссылки будет храниться в этом поле, если целевая строка имеет длину менее 60 байт. В противном случае либо экстенты, либо карты блоков будут использоваться для выделения блоков данных для хранения цели ссылки.

Я пробовал с целью короче/длиннее 60B, но разницы нет.

$ cat test.sh
#!/usr/bin/env bash
foo="foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo"
mkdir /tmp/test
cd /tmp/test
touch a
ln -s /tmp/test/a b
ls -li
if [ a -ef b ]
then
  echo b : same device or inode of a
 else
  echo b : different device or inode of a
fi
mkdir /tmp/test/${foo}
cd /tmp/test/${foo}
touch c
ln -s /tmp/test/${foo}/c d
ls -li
if [ c -ef d ]
then
  echo d : same device or inode of c
else
  echo d : different device or inode of c
fi
$ ./test.sh
156490 -rw-rw-r-- 1 msi msi  0 nov.  25 23:55 a                                                                                                                                                                                                
156491 lrwxrwxrwx 1 msi msi 11 nov.  25 23:55 b -> /tmp/test/a                                                                                                                                                                                 
b : same device or inode of a                                                                                                                                                                                                                  
total 4                                                                                                                                                                                                                                        
156494 -rw-rw-r-- 1 msi msi   0 nov.  25 23:55 c
156495 lrwxrwxrwx 1 msi msi 155 nov.  25 23:55 d -> /tmp/test/foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo/c
d : same device or inode of c

Иноды разные, но тест прошел успешно, и я не увидел, что не так.


person F4240    schedule 25.11.2016    source источник
comment
Обратите внимание, что в верхней части раздела руководства, на которое вы ссылаетесь, написано: Если не указано иное, основные файлы, работающие с файлами, следуют символическим ссылкам и работают с целью ссылки, а не с самой ссылкой.. То есть, за исключением проверки того, является ли что-то символической ссылкой (примерно), он использует системный вызов stat(), а не системный вызов lstat(). Информация ext4 просто о дисковом хранилище для пути, на который указывает символическая ссылка; это не влияет на функциональность (но незначительно влияет на производительность, поскольку для очень длинных символических ссылок необходимо читать дополнительный блок диска).   -  person Jonathan Leffler    schedule 27.11.2016
comment
Я думал, что конкретная инструкция будет исчерпывающей :/ Спасибо за это полное объяснение.   -  person F4240    schedule 27.11.2016


Ответы (1)


Похоже, документация в некоторых местах вводит в заблуждение. Из http://www.tldp.org/LDP/abs/html/fto.html:

f1 -ef f2

файлы f1 и f2 являются жесткими ссылками на один и тот же файл

Как вы уже сами убедились, это выражение возвращает true не только для жестких ссылок, но и для мягких ссылок на один и тот же файл.

Вместо этого используйте stat:

if [ "$(stat -c "%d:%i" FILE1)" == "$(stat -c "%d:%i" FILE2)" ]

Источник: https://superuser.com/questions/196572/check-if-two-paths-are-pointing-to-the-same-file

person Ruud Helderman    schedule 26.11.2016