У меня есть скрипт для рекурсивного создания символических ссылок в моем домашнем каталоге на мой каталог настроек, чтобы держать файлы под контролем версий. Я бы хотел, чтобы он пропускал файлы, которые уже связаны симлинками через родительский каталог. То есть, если у меня есть эти файлы/каталоги:
~/foo/ -> ~/settings/foo/
~/settings/foo/
~/settings/foo/bar
, как проверить, что ~/foo/bar и ~/settings/foo/bar — это один и тот же файл?
Редактировать: Ого, еще несколько минут поиска выявилиотвечать:readlink -f $path
решение1
Если два файла имеют одинаковый deviceID и inode, это один и тот же файл. stat
Инструмент командной строки позволяет легко это найти, и это решение совместимо с оболочкой POSIX.
if [ "$(stat -L -c %d:%i FILE1)" = "$(stat -L -c %d:%i FILE2)" ]; then
echo "FILE1 and FILE2 refer to a single file, with one inode, on one device."
else
echo "no match"
fi
Флаг -L
в каждом случае stat
означает, что это работает как для файлов с символическими, так и для файлов с жесткими ссылками.
решение2
Во многих оболочках есть -ef
встроенный оператор test
(или его синоним [
), позволяющий проверить, указывают ли два пути натот же существующий файл(переход по символическим ссылкам). Сюда входят bash, dash, pdksh, ksh88, ksh93 и zsh, но не POSIX sh. В bash, ksh или zsh вы также можете использовать -ef
в [[ … ]]
условной конструкции.
if ! [ "$1" -ef "$2" ]; then # $1 and $2 are different files
решение3
Для мягких ссылок (созданных с помощью ln -s
) можно использовать realpath
. Однако для жестких ссылок это не сработает.