Як перевірити, чи існує симпосилання


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

Відповіді:


327

-Lповертає істину, якщо "файл" існує і є символічним посиланням (пов'язаний файл може існувати або не існувати). Ви хочете -f(повертає true, якщо файл існує і є звичайним файлом) або, можливо, просто-e (повертає true, якщо файл існує незалежно від типу).

Згідно сторінці керівництва GNU , -hідентично -L, але в відповідно до BSD сторінки керівництва , вона не визначає, чи використовується

-h file Щоправда, якщо файл існує і є символічним посиланням. Цей оператор зберігається для сумісності з попередніми версіями цієї програми. Не покладайтеся на його існування; використовувати -L натомість.


2
Я дивлюсь, чи існує симпосилання НЕ. ! -h або! -L повинен працювати для посилань,! -e повинен працювати інакше.
ведмідь

48
Щоб допомогти всім, хто знайде це через Google, як я, повний синтаксис !- це, if ! [ -L $mda ]; then .... fi наприклад, поставити знак оклику поза квадратними дужками.
Сем

19
Просто хотів додати трохи підказки, наданої @Sam; виконуючи подібні операції, обов'язково введіть своє ім'я файлу в лапки, щоб уникнути проблем з пробілами. наприклад if [ ! -L "$mda" ]; then ... fi(зверніть увагу: if [ ! ... ]і if ! [ ... ]однакові :)
Thomas Vervest

2
ви дійсно бачите різницю між -L і -h? в моєму bash (версія 4.2.53 (1) -release (x86_64-redhat-linux-gnu) man bash однаковий і для -L і -h, і вони поводяться однаково, тобто перевіряють, що файл фактично є посиланням і не
Мені все

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}"не вдається, якщо симпосилання існує, але її ціль не існує.
Флейм

1
Той самий результат, що і Flimm. Я в ОС X. Для мене -L і -h працюють для посилань, але не -e або -f.
pauljm

2
@Flimm, тож якщо я просто хочу перевірити, чи прийнято ім’я файлу (чи це файл чи символьна посилання без цілі), який найкращий спосіб це зробити? мабуть -е не працює
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, можна перевірити, чи посилання також є дійсним (посилання на каталог чи файл). Під час голосування за ці рішення, оскільки я вважаю важливим зафіксувати цей аспект.
Torbjörn Österdahl

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 повинен працювати для посилань,! -e повинен працювати інакше.
ведмідь

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.