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


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.


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

4

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

См man test.


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

Первый вызов неверен, если файл существует, но не является ссылкой или является висячей ссылкой. Второе неверно, если путь представляет собой висячую символическую ссылку.
— Джонатан Томер
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.