3

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

if [[ -L "$out_dir" && -d "$out_dir" ]]
then
    echo "Dir is a symlink"
else
    echo "Dir is not a symlink"
fi

Однако это не удается. Некоторые эксперименты:

bash-3.2$ ls -ail ..
total 16
8004466 drwxr-xr-x  10 username  1177235957  340 Jul 18 15:41 ./
1020189 drwxr-xr-x  10 username  1177235957  340 Jul 18 15:16 ../
8004467 drwxr-xr-x  12 username  1177235957  408 Jul 18 15:16 .git/
8004528 -rw-r--r--   1 username  1177235957  501 Jul 18 15:16 .gitignore
8004919 lrwxr-xr-x   1 username  1177235957   22 Jul 18 15:41 Dependencies -> ../../lmi/Dependencies

так ../Dependencies , согласно ls, являются символической ссылкой, однако:

bash-3.2$ test -L ../Dependencies
bash-3.2$ echo $?
0
bash-3.2$ test -h ../Dependencies
bash-3.2$ echo $?
0

Разве оба из них не должны возвращать 1? Я что-то неправильно понимаю о том, как это должно работать? Как можно достичь моей цели - определить, является ли файл символической ссылкой, указывающей на каталог?

3 ответа3

3

Значения выхода из вашего эксперимента верны. Когда утилита test оценивает выражение, если выражение оценивается как true, test возвращает нулевое (true) состояние выхода; в противном случае возвращается 1 (false).

Итак, в вашем примере test -L ../Dependencies возвращает 0 (истина), потому что ../Dependencies является символической ссылкой. Если ../Dependencies не были символической ссылкой, test выдаст 1 (false).

Сценарий оболочки, if оператор верен, но вы можете добавить команды echo чтобы увидеть, есть ли другие проблемы при запуске скрипта оболочки. Например, вы можете добавить две команды echo перед оператором if :

echo "path is '$PWD'"
echo "out_dir is '$out_dir'"
2

Я бы выбрал более замысловатое решение (так как это подходит моей личности, но сейчас это не важно ...)

for x in $(ls -lp|egrep ^[dl].*\/$); do 
   case $(echo $x|cut -c 1) in 
      "d") echo "This is a dir";; 
      "l") echo "This is a link";;
   esac
done

Вкратце, ls -lp печатает длинный формат с косой чертой для всех каталогов. Самый первый символ длинного формата сообщает нам режим (d для каталогов, l для ссылки, - для обычных файлов и т.д.). Учитывая эту информацию, мы можем использовать egrep для фильтрации наших ls для списков каталогов и ссылок, которые заканчиваются на / и использовать case для дальнейшей фильтрации нашего списка. Примечание: этот цикл также будет отфильтровывать связанные файлы из-за опции -p в ls

1

Я получил следующее решение:

function is_sym_link()
{
    readlink $1 > /dev/null
    return $?
}

Это может не охватывать все случаи, но для моего окружения этого достаточно. Я не знаю, почему оригинал не работал, к сожалению.

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