Как проверить, существует ли символическая ссылка

208

Я пытаюсь проверить, существует ли символическая ссылка в bash. Вот что я попробовал.

mda=/usr/mda
if [ ! -L $mda ]; then
  echo "=> File doesn't exist"
fi


mda='/usr/mda'
if [ ! -L $mda ]; then
  echo "=> File doesn't exist"
fi

Однако это не работает. Если '!' опущено, оно никогда не срабатывает. И если '!' там, это срабатывает каждый раз.

медведь
источник
2
для чего стоит, если вы используете [[! -D $ mda]] отлично работает ..
DMin

Ответы:

328

-Lвозвращает true, если «файл» существует и является символической ссылкой (связанный файл может существовать или не существовать). Вы хотите -f(возвращает true, если файл существует и является обычным файлом) или, может быть, просто -e(возвращает true, если файл существует независимо от типа).

Согласно man-странице GNU , -hидентична -L, но согласно man-странице BSD , она не должна использоваться:

-h file Истинно, если файл существует и является символической ссылкой. Этот оператор сохранен для совместимости с предыдущими версиями этой программы. Не полагайтесь на его существование; используйте вместо этого -L.

drysdam
источник
2
Я смотрю, чтобы увидеть, если символическая ссылка не существует. ! -h или! -L должны работать для символических ссылок,! -е должно работать иначе.
медведь
48
Для того, чтобы помочь всем , кто находит это через Google , как я, полный синтаксис использования !является if ! [ -L $mda ]; then .... fi то поставить восклицательный знак вне квадратных скобок.
Сэм
19
Просто хотел добавить кое-что к совету @Sam; при выполнении таких операций не забудьте указать имя файла в кавычках, чтобы избежать проблем с пробелами. например if [ ! -L "$mda" ]; then ... fi(примечание: if [ ! ... ]и if ! [ ... ]идентичны :)
Томас Вервест
2
Вы действительно видите разницу между -L и -h? в моем bash (версия 4.2.53 (1) -релиз (x86_64-redhat-linux-gnu) man bash идентичен как для -L, так и для -h, и они ведут себя одинаково, то есть проверяют, что файл действительно является ссылкой, и не важно, существует ли ссылка на файл или нет.
Philippe Lhardy
3
Да -Lи -hтак же . man testтакже подтверждает это.
Sparhawk
39

-L - это проверка на наличие файла, а также символическая ссылка

Если вы не хотите проверять, является ли файл символической ссылкой, а просто проверить, существует ли он независимо от типа (файл, каталог, сокет и т. Д.), Используйте -e

Таким образом, если файл действительно файл, а не просто символическая ссылка, вы можете выполнить все эти тесты и получить состояние выхода, значение которого указывает на состояние ошибки.

if [ ! \( -e "${file}" \) ]
then
     echo "%ERROR: file ${file} does not exist!" >&2
     exit 1
elif [ ! \( -f "${file}" \) ]
then
     echo "%ERROR: ${file} is not a file!" >&2
     exit 2
elif [ ! \( -r "${file}" \) ]
then
     echo "%ERROR: file ${file} is not readable!" >&2
     exit 3
elif [ ! \( -s "${file}" \) ]
then
     echo "%ERROR: file ${file} is empty!" >&2
     exit 4
fi
Корин
источник
16
-e "${file}"терпит неудачу, если символическая ссылка существует, но ее цель не существует.
Flimm
1
Тот же результат, что и у Flimm. Я на OS X. Для меня -L и -h работают для символических ссылок, но не -e или -f.
pauljm
2
@Flimm, так что, если я просто хочу проверить, берется ли имя файла (будь то файл или символическая ссылка без цели), каков наилучший способ сделать это? очевидно -e не работает
dragonxlwang
38

Вы можете проверить наличие символической ссылки и ее отсутствие:

[ -L ${my_link} ] && [ -e ${my_link} ]

Итак, полное решение:

if [ -L ${my_link} ] ; then
   if [ -e ${my_link} ] ; then
      echo "Good link"
   else
      echo "Broken link"
   fi
elif [ -e ${my_link} ] ; then
   echo "Not a link"
else
   echo "Missing"
fi
Чен Леви
источник
2
-L проверить, есть ли символическая ссылка, сломана или нет. Комбинируя с -e, можно проверить, действительна ли ссылка (ссылка на каталог или файл). Голосовать за это решение, так как я считаю важным охватить этот аспект.
Торбьерн Эстердаль
14

Может быть, это то, что вы ищете. Проверить, существует ли файл и не является ли он ссылкой.

Попробуйте эту команду:

file="/usr/mda" 
[ -f $file ] && [ ! -L $file ] && echo "$file exists and is not a symlink"
линчевать
источник
8

Как насчет использования readlink?

# if symlink, readlink returns not empty string (the symlink target)
# if string is not empty, test exits w/ 0 (normal)
#
# if non symlink, readlink returns empty string
# if string is empty, test exits w/ 1 (error)
simlink? () {
  test "$(readlink "${1}")";
}

FILE=/usr/mda

if simlink? "${FILE}"; then
  echo $FILE is a symlink
else
  echo $FILE is not a symlink
fi
popedotninja
источник
4

Является ли файл действительно символической ссылкой? Если нет, то обычным тестом на существование является -rили -e.

См man test.

DigitalRoss
источник
3

Если вы проверяете наличие файлов, вы хотите -e, а не -L. -L тесты на символическую ссылку.

Андрей Лазарь
источник
Я смотрю, чтобы увидеть, если символическая ссылка не существует. ! -h или! -L должны работать для символических ссылок,! -е должно работать иначе.
медведь
3
Что вы хотите, не ясно. Файл существует и не является символической ссылкой? Затем проверьте оба -e и! -H.
Андрей Лазарь
3
  1. Сначала вы можете сделать с этим стилем:

    mda="/usr/mda"
    if [ ! -L "${mda}" ]; then
      echo "=> File doesn't exist"
    fi
  2. если вы хотите сделать это в более продвинутом стиле, вы можете написать это так:

    #!/bin/bash
    mda="$1"
    if [ -e "$1" ]; then
        if [ ! -L "$1" ]
        then
            echo "you entry is not symlink"
        else
            echo "your entry is symlink"
        fi
    else
      echo "=> File doesn't exist"
    fi

результат выше, как:

root@linux:~# ./sym.sh /etc/passwd
you entry is not symlink
root@linux:~# ./sym.sh /usr/mda 
your entry is symlink
root@linux:~# ./sym.sh 
=> File doesn't exist
Амин Шатери
источник
Первый вызов неверен, если файл существует, но не является ссылкой или является висячей ссылкой. Второе неверно, если путь представляет собой висячую символическую ссылку.
Джонатан Томер