Como verificar se existe um link simbólico

208

Estou tentando verificar se existe um link simbólico no bash. Aqui está o que eu tentei.

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

No entanto, isso não funciona. E se '!' é deixado de fora, nunca é acionado. E se '!' está lá, ele dispara toda vez.

Urso
fonte
2
pelo valor, se você usar [[! -D $ mda]] funciona muito bem ..
DMin

Respostas:

328

-Lretorna true se o "arquivo" existe e é um link simbólico (o arquivo vinculado pode ou não existir). Você deseja -f(retorna true se o arquivo existe e é um arquivo regular) ou talvez apenas -e(retorna true se o arquivo existe independentemente do tipo).

De acordo com a página de manual do GNU , -hé idêntico -L, mas de acordo com a página de manual do BSD , não deve ser usado:

-h file Verdadeiro se o arquivo existir e for um link simbólico. Este operador é mantido para compatibilidade com versões anteriores deste programa. Não confie em sua existência; use -L em vez disso.

Drysdam
fonte
2
Eu estou olhando para ver se um link simbólico NÃO existe. ! -h ou! -L deve funcionar para links simbólicos,! -e deve funcionar de outra forma.
urso
48
Para ajudar alguém que encontrar isso no Google como eu, a sintaxe completa usada !é, por exemplo, if ! [ -L $mda ]; then .... fi colocar o ponto de exclamação fora dos colchetes.
Sam
19
Só queria adicionar um pouquinho à dica dada pelo @Sam; ao fazer esse tipo de operação, coloque o nome do arquivo entre aspas, para evitar problemas com espaços em branco. por exemplo, if [ ! -L "$mda" ]; then ... fi(nota: if [ ! ... ]e if ! [ ... ]são idênticos :)
Thomas Vervest
2
você realmente vê alguma diferença entre -L e -h? no meu bash (versão 4.2.53 (1) -release (x86_64-redhat-linux-gnu) o man bash é idêntico para ambos -L e -h e eles se comportam da mesma forma, ou seja, verificam se o arquivo realmente é um link e não se importa se o
link
3
Sim, -Le -hsão iguais . man testtambém confirma isso.
Sparhawk
39

-L é o teste para o arquivo existente e também é um link simbólico

Se você não deseja testar se o arquivo é um link simbólico, mas apenas teste para ver se ele existe, independentemente do tipo (arquivo, diretório, soquete etc.) e use -e

Portanto, se o arquivo for realmente um arquivo e não apenas um link simbólico, você poderá executar todos esses testes e obter um status de saída cujo valor indique a condição de erro.

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
Corin
fonte
16
-e "${file}"falha se o link simbólico existe, mas seu destino não existe.
Flimm
1
Mesmo resultado que Flimm. Estou no OS X. Para mim, -L e -h trabalham para links simbólicos, mas não -e ou -f.
pauljm
2
@ Limlim, então se eu só quero testar se um nome de arquivo é usado (seja um arquivo ou link simbólico sem destino existente), qual é a melhor maneira de fazer isso? aparentemente -e não trabalho
dragonxlwang
38

Você pode verificar a existência de um link simbólico e se ele não está quebrado com:

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

Portanto, a solução completa é:

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
Chen Levy
fonte
2
Teste -L se houver um link simbólico, quebrado ou não. Ao combinar com -e, é possível testar se o link também é válido (vinculação a um diretório ou arquivo). A votação antecipada dessas soluções, pois acho importante capturar esse aspecto.
Torbjörn Österdahl 03/03
14

Talvez seja isso que você está procurando. Para verificar se existe um arquivo e não é um link.

Tente este comando:

file="/usr/mda" 
[ -f $file ] && [ ! -L $file ] && echo "$file exists and is not a symlink"
Lynch
fonte
8

Que tal usar 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
fonte
4

O arquivo é realmente um link simbólico? Caso contrário, o teste usual de existência é -rou-e .

Veja man test.

DigitalRoss
fonte
3

Se você está testando a existência do arquivo, deseja -e não -L. -L testa um link simbólico.

Andrew Lazarus
fonte
Eu estou olhando para ver se um link simbólico NÃO existe. ! -h ou! -L deve funcionar para links simbólicos,! -e deve funcionar de outra forma.
urso
3
O que você quer não está claro. O arquivo existe e não é um link simbólico? Em seguida, teste tanto -e e! -H.
Andrew Lazarus
3
  1. primeiro você pode fazer com este estilo:

    mda="/usr/mda"
    if [ ! -L "${mda}" ]; then
      echo "=> File doesn't exist"
    fi
  2. se você quiser fazê-lo em um estilo mais avançado, você pode escrever como abaixo:

    #!/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

o resultado acima é como:

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
Amin Shateri
fonte
A primeira chamada estará incorreta se o arquivo existir, mas não for um link ou for um link danificado. O segundo está errado se o caminho for um link simbólico pendente.
Jonathan Tomer