Горячий, чтобы заставить diff проверять ссылку на символическую ссылку?


8

В Linux можно использовать команду diffдля проверки различий файлов. Я использую его для проверки различий между двумя модулями, оба скопированы в /tmp.

Однако оба модуля имеют символические ссылки, которые могут не указывать на правильный файл, так как модули были скопированы в /tmpкаталог. Но это не имеет значения. Я хочу проверить, совпадают ли символические ссылки.

Например, в одном модуле символическая ссылка читает

/home/test/file1

а в другой символическая ссылка гласит:

/etc/rc.d/whatever

diffтеперь выдает ошибку, потому что - в общем - он не может найти файл. Но я хочу diffсказать: «Эй, эти символические ссылки не одинаковы», независимо от того, указывают ли ссылки на действительные файлы или нет.

Вопрос: Как это можно diffсделать, то есть не пытаясь переходить по ссылкам, а разграничивать сами ссылки?

Ответы:


6

Попробуйте GNU diffверсии 3.3 или новее с --no-dereferenceопцией (и предположительно опцией --recursive):

diff --recursive --no-dereference tree1root tree2root

Не могли бы вы немного уточнить это? Возможно, приведите пример того, как это можно использовать? Это дает хороший ответ, но мы хотели бы, чтобы наши ответы были более четкими и подробными.
Тердон

3

Начиная с версии 3.3, GNU diff не поддерживает разыменование символических ссылок, но затем сравнивает пути, на которые они указывают.

Установите GNU diffutils> = 3.3 и используйте опцию --no-dereference; нет короткого варианта для этого.

Диагностика будет молчать, если пути равны или:

Symbolic links /tmp/noderef/a/symlink and /tmp/noderef/b/symlink differ

если пути различаются.


1

С инструментами GNU:

diff <(cd dir1 && find . -type l -printf '%p -> %l\n'|sort) \
     <(cd dir2 && find . -type l -printf '%p -> %l\n'|sort)

Строго говоря, это не может различить вызываемую символическую ссылку, aкоторая указывает на, b -> cи вызываемую ссылку , a -> bкоторая указывает на c, не говоря уже о проблемах с именами файлов, содержащими символы новой строки, но это обеспечивает более разборчивый вывод, чем более надежный:

diff <(cd dir1 && find . -type l -printf '%p // %l\0'|tr '\n\0' '\0\n'|sort) \
     <(cd dir2 && find . -type l -printf '%p // %l\0'|tr '\n\0' '\0\n'|sort)

Там мы используем //в качестве разделителя (что не может произойти в противном случае при выводе findfor %p) и преобразуем символы новой строки в символы NUL (что не может произойти при расширении %pnor %l).


1

Если я правильно понимаю, вы хотите проверить, что символические ссылки указывают на то же теоретическое назначение, или что, если одна не является символической ссылкой, другой файл ссылается на тот же файл. Это должно делать то, что вы хотите:

#!/bin/bash

if [[ "$(readlink -m -- "$1")" == "$(readlink -m -- "$2")" ]]; then
    echo "files match"
else
    echo "files don't match"
    exit 1
fi
$ > foo 
$ ln -s foo bar
$ ln -s foo baz
$ ./script bar baz
files match
$ ./script bar foo
files match
$ ln -sf qux bar
$ ./script bar foo
files don't match

@StephaneChazelas Это моя ошибка, я хотел использовать -m, а не -f. Спасибо!
Крис Даун

Строго говоря, это не сработало бы, если бы единственной разницей было количество конечных символов новой строки в целях символических ссылок.
Стефан Шазелас

Я бы тоже не использовал -m.
Стефан Шазелас

@StephaneChazelas По какой причине? Без этого относительные символические ссылки, которые действительно указывают на один и тот же файл, не смогут сравниться.
Крис Даун

Если /home/test/file1это символическая ссылка /etc/rc.d/whatever, или они обе символические ссылки /, он сообщит, что они одинаковы. Я думаю, что ОП хочет видеть разницу в «пути», хранящемся в символической ссылке, а не в том, разрешают ли они один и тот же файл (для которого у вас есть [[ a -ef b ]]).
Стефан Шазелас
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.