3

Как я могу проверить, что данный обычный файл пути f является потомком каталога пути d . Если бы не символические ссылки, я бы просто проверил, является ли d (с завершающим слешем) префиксом к f . Теперь с символическими ссылками это немного усложняется, так как я мог найти физические пути предков f и сравнить каждый из них с физическим путем d . Тем не менее, я считаю, что для этого может быть полезна пользовательская утилита.

2 ответа2

4
  1. Если предки файла определены как каталог, содержащий его, и предки этого каталога, т. Е. Потомки каталога являются его записями и (для записей, которые являются каталогами) их собственными потомками:

    Предполагая, что $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" .

  2. Если потомки каталога $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 .

1

Моя команда 'ls' имеет флаг "--dereference-command-line-symlink-to-dir", который показывает полный путь к файлу. Это 'ls' из GNU coreutils 6.9.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .