Como posso encontrar links simbólicos quebrados

240

Existe uma maneira de encontrar todos os links simbólicos que não apontam para nenhum outro?

find ./ -type l

me dará todos os links simbólicos, mas não faz distinção entre links que vão para algum lugar e links que não vão.

Atualmente estou fazendo:

find ./ -type l -exec file {} \; |grep broken

Mas eu estou querendo saber quais soluções alternativas existem.

    
por gabe. 15.03.2012 / 17:29

9 respostas

305

Sugiro strongmente que não use find -L para a tarefa (veja abaixo a explicação). Aqui estão algumas outras maneiras de fazer isso:

  • Se você quiser usar um método "pure find ", ele deve ser assim:

    find . -xtype l
    

    ( xtype é um teste realizado em um link desreferenciado) Isso pode não estar disponível em todas as versões de find , no entanto. Mas há outras opções também:

  • Você também pode executar test -e no comando find :

    find . -type l ! -exec test -e {} \; -print
    
  • Mesmo alguns truques de grep poderiam ser melhores (ou seja, mais seguros ) do que find -L , mas não exatamente como os apresentados na pergunta (em todas as linhas de saída, incluindo nomes de arquivos):

     find . -type l -exec sh -c 'file -b "$1" | grep -q ^broken' sh {} \; -print
    

O truque find -L citou por solo de commandlinefu parece legal e hacky, mas tem uma armadilha muito perigosa : Todas as ligações simbólicas são seguidas. Considere o diretório com os conteúdos apresentados abaixo:

$ ls -l
total 0
lrwxrwxrwx 1 michal users  6 May 15 08:12 link_1 -> nonexistent1
lrwxrwxrwx 1 michal users  6 May 15 08:13 link_2 -> nonexistent2
lrwxrwxrwx 1 michal users  6 May 15 08:13 link_3 -> nonexistent3
lrwxrwxrwx 1 michal users  6 May 15 08:13 link_4 -> nonexistent4
lrwxrwxrwx 1 michal users 11 May 15 08:20 link_out -> /usr/share/

Se você executar find -L . -type l nesse diretório, todos os /usr/share/ também serão pesquisados (e isso pode demorar muito) 1 . Para um comando find que é "imune a links de saída", não use -L .

1 Isso pode parecer um pequeno inconveniente (o comando "apenas" demorará a percorrer todo o /usr/share ) - mas pode ter consequências mais graves. Por exemplo, considere ambientes chroot: Eles podem existir em algum subdiretório do sistema de arquivos principal e conter links simbólicos para locais absolutos. Esses links podem parecer quebrados para o sistema "externo", porque eles apontam apenas para lugares apropriados quando você entra no chroot. Também lembro que alguns gerenciadores de inicialização usavam links simbólicos em /boot que faziam sentido apenas em uma fase inicial de inicialização, quando a partição de inicialização era montada como / .

Então, se você usar o comando find -L para encontrar e excluir links simbólicos quebrados de algum diretório aparentemente inofensivo, você pode até quebrar o sistema ...

    
por 15.05.2012 / 09:01
35

O comando symlinks do link pode ser usado para Identifique links simbólicos com uma variedade de características. Por exemplo:

$ rm a
$ ln -s a b
$ symlinks .
dangling: /tmp/b -> a
    
por 15.03.2012 / 18:38
25

Como o rozcietrzewiacz já comentou, find -L pode ter conseqüências inesperadas de expandir a pesquisa em diretórios com links simbólicos, portanto, não é a abordagem ideal. O que ninguém mencionou ainda é que

find /path/to/search -xtype l

é o comando mais conciso e logicamente idêntico para

find /path/to/search -type l -xtype l

Nenhuma das soluções apresentadas até agora detectará links simbólicos cíclicos, que é outro tipo de quebra. esta questão aborda a portabilidade . Para resumir, a maneira portátil de encontrar links simbólicos quebrados, incluindo links cíclicos, é:

find /path/to/search -type l -exec test ! -e {} \; -print

Para mais detalhes, consulte esta pergunta ou ynform.org . É claro que a fonte definitiva para tudo isso é a documentação do findutils .

    
por 29.09.2012 / 16:02
7

Acredito que adicionar o -L flag ao seu comando permitirá que você se livre do grep:

$ find -L . -type l

link

do homem:

 -L      Cause the file information and file type (see stat(2)) returned 
         for each symbolic link to be those of the file referenced by the
         link, not the link itself. If the referenced file does not exist,
         the file information and type will be for the link itself.
    
por 15.03.2012 / 17:52
6

Se você precisar de um comportamento diferente, esteja o link quebrado ou cíclico, você também pode usar% Y com find:

$ touch a
$ ln -s a b  # link to existing target
$ ln -s c d  # link to non-existing target
$ ln -s e e  # link to itself
$ find . -type l -exec test ! -e {} \; -printf '%Y %p\n' \
   | while read type link; do
         case "$type" in
         N) echo "do something with broken link $link" ;;
         L) echo "do something with cyclic link $link" ;;
         esac
      done
do something with broken link ./d
do something with cyclic link ./e

Este exemplo é copiado de esta postagem (site excluído) .

Referência

por 26.12.2012 / 07:56
1

find -L . -type l |xargs symlinks fornecerá a você se o link existe ou não por arquivo de foundfile.

    
por 30.04.2013 / 08:37
1

Isso imprimirá os nomes dos links simbólicos quebrados no diretório atual.

for l in $(find . -type l); do cd $(dirname $l); if [ ! -e "$(readlink $(basename $l))" ]; then echo $l; fi; cd - > /dev/null; done

Funciona no Bash. Não sei sobre outras conchas.

    
por 24.10.2014 / 16:33
1

Eu uso isso para o meu caso e funciona muito bem, já que conheço o diretório para procurar por links simbólicos quebrados:

find -L $path -maxdepth 1 -type l

e minha pasta inclui um link para /usr/share , mas não o percorre. Links entre dispositivos e aqueles que são válidos para chroots, etc. ainda são uma armadilha, mas para o meu caso de uso é suficiente.

    
por 08.08.2015 / 16:01
1

Resposta simples e simples, que é uma variação da versão do OP. Às vezes, você só quer algo fácil de digitar ou lembrar:

find . | xargs file | grep -i "broken symbolic link"
    
por 18.04.2018 / 20:13