Как я могу проверить, что данный обычный файл пути f является потомком каталога пути d . Если бы не символические ссылки, я бы просто проверил, является ли d (с завершающим слешем) префиксом к f .
Теперь с символическими ссылками это немного усложняется, так как я мог найти физические пути предков f и сравнить каждый из них с физическим путем d . Тем не менее, я считаю, что для этого может быть полезна пользовательская утилита.
2 ответа
Если предки файла определены как каталог, содержащий его, и предки этого каталога, т. Е. Потомки каталога являются его записями и (для записей, которые являются каталогами) их собственными потомками:
Предполагая, что
$fявляется путем к обычному файлу (а не путем символьной ссылки), вы можете найти «реальный» каталог, содержащий его, с помощью команды$(cd -- "$(dirname "$f")" && command -p pwd). Аналогичным образом найдите «реальное» местоположение каталога$dс помощью$(cd -- "$d" && command -p pwd). В bash/ksh/zsh вы можете заменитьcommand -p pwdнаpwd -P.Если
$fможет быть символической ссылкой, это более сложно. В некоторых системах есть командаreadlink, например, вы можете использовать$(dirname "$(readlink -f -- "$f"))с относительно свежим GNU coreutils, но обратите внимание, что есть другие системы с несовместимой командойreadlinkили ее нет все.Обратите внимание, что файл может быть перемещен между временем проверки и временем использования результата. Есть также угловые случаи, когда вопрос не имеет четкого ответа да / нет, например, когда путь от каталога до файла проходит точку монтирования.
Если вам нужно знать, какая файловая система
$fвключена , запуститеdf "$f".Если потомки каталога
$dопределены как файлы, которым можно дать имя в форме$d/x1/x2/.../xnгдеxiможет быть каталогами или символическими ссылками:Тестирование этого свойства требует обхода всего дерева каталогов с корнем в
$d, следуя всем символическим ссылкам. Следующая команда должна сделать это (предупреждение, введенное непосредственно в браузер; требует GNU find):[ -n "$(find -L "$d" -samefile "$f" -print -quit)" ]Если
$fимеет жесткие ссылки, он может получить доступ к файлу$fчерез другое имя. Если вам требуется, чтобы файл находился под именем$f, он становится более сложным; Вот попытка (опять же, набранная прямо в браузере; требует GNU find и GNU grep; не предполагает никаких новых строк в именах файлов):f_directory="$(cd -- "$(dirname "$f")" && command -p pwd)" f_truename="$f_directory/$(basename "$f")" [ -n "$(find -L "$(cd "$d" && command -p pwd)" -exec readlink -f \; | grep -F -q -x "$f_truename")" ]Независимо от того, какое именно определение вы выберете, это свойство не очень надежно, поскольку вы можете изменить его значение, добавив или удалив символическую ссылку глубоко под
$d.
Моя команда 'ls' имеет флаг "--dereference-command-line-symlink-to-dir", который показывает полный путь к файлу. Это 'ls' из GNU coreutils 6.9.
