Procurando pelo utilitário POSIX para testar se filename é um link simbólico

6

Eu sei que alguns shells suportam pelo menos operadores de teste de arquivo que detectam quando um nome de arquivo nomeia um symlink.

Existe um utilitário POSIX 1 que fornece a mesma funcionalidade?

1 Eu posso não estar usando a terminologia correta aqui. O que quero dizer com "utilitário" é um executável independente que vive em algum lugar abaixo de /bin , /usr/bin , etc., em oposição a um shell integrado.

    
por kjo 10.09.2015 / 15:57

4 respostas

21

Você está procurando test :

-h pathname

True if pathname resolves to a file that exists and is a symbolic link. False if pathname cannot be resolved, or if pathname resolves to a file that exists but is not a symbolic link. If the final component of pathname is a symlink, that symlink is not followed.

A maioria das shells tem isso como um builtin, mas test também existe como um programa independente, que pode ser chamado de outros programas sem invocar um shell intermediário. Este é o caso da maioria dos builtins que os shells podem ter, exceto aqueles que atuam no próprio shell (builtins especiais como break , export , set ,…).

[ -h pathname ] é equivalente a test -h pathname ; [ funciona exatamente da mesma maneira que test , exceto que [ requer um argumento ] extra no final. [ , como test , existe como um programa independente.

Por exemplo:

$ ln -s foo bar
$ /usr/bin/test -h bar && echo y
y
    
por 10.09.2015 / 16:07
3

Dois utilitários podem fazer isso por você, file e readlink :

  1. file some_symlink exibirá some_symlink: symbolic link to 'some_target'
  2. readlink some_symlink sairá com o código 0, enquanto readlink some_file sairá com o código 1

Observe que código de saída é armazenado na variável $? e pode ser exibido com echo $? .

    
por 10.09.2015 / 16:13
1

Há também stat :

$ touch test
$ ln -s test test_l

$ stat test
  File: 'test'
  Size: 0           Blocks: 0          IO Block: 4096   regular empty file
Device: fc00h/64512d    Inode: 4309        Links: 1
Access: (0664/-rw-rw-r--)  Uid: ( 1000/ vagrant)   Gid: ( 1000/ vagrant)
Access: 2015-09-11 11:37:59.864165922 +0000
Modify: 2015-09-11 11:37:59.864165922 +0000
Change: 2015-09-11 11:37:59.864165922 +0000
 Birth: -

$ stat test_l
  File: 'test_l' -> 'test'
  Size: 4           Blocks: 0          IO Block: 4096   symbolic link
Device: fc00h/64512d    Inode: 7179        Links: 1
Access: (0777/lrwxrwxrwx)  Uid: ( 1000/ vagrant)   Gid: ( 1000/ vagrant)
Access: 2015-09-11 11:38:07.220173955 +0000
Modify: 2015-09-11 11:38:07.220173955 +0000
Change: 2015-09-11 11:38:07.220173955 +0000
 Birth: -

$ stat -c "%F" test
regular empty file

$ stat -c "%F" test_l
symbolic link
    
por 11.09.2015 / 13:40
-2

Como alternativa, você pode usar um script simples:

#!/bin/bash    
ls -alFQ | grep '^l'

O mantra Unix é ter pequenos utilitários simples que podem ser encadeados para conseguir tarefas complexas. Então, embora isso tecnicamente não seja um utilitário POSIX, é muito próximo de um.

Se você quiser se interessar, só pode selecionar qual parte da string retornar:

#!/bin/bash    
ls -alFQ | grep '^l' | tr -s ' ' | cut -d ' ' -f 11

O -f 11 retorna o arquivo para o qual o link está apontando e -f 10 retorna o nome do link. Isso só funciona se os nomes dos arquivos não tiverem espaços, senão fica complicado - provavelmente pode ser feito, mas você terá que escapar dos espaços em branco ou usar um padrão, que é mais do que eu gostaria de escrever no momento .

Se você quiser algo que retorne 0/1:

    #!/bin/bash
    if [[ -n $(ls -alFQ | grep '^l') ]]; then
        exit
    else
        exit 1
    fi
    
por 10.09.2015 / 22:02

Tags