Как я могу проверить, что данный обычный файл пути 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.