Como usar o teste -h ou testar -L no OSX?

3

Estou tentando detectar em um script de shell se um arquivo é um link simbólico apontando para um diretório. Isso é o que estou fazendo:

if [[ -L "$out_dir" && -d "$out_dir" ]]
then
    echo "Dir is a symlink"
else
    echo "Dir is not a symlink"
fi

No entanto, isso falha. Alguma experimentação:

bash-3.2$ ls -ail ..
total 16
8004466 drwxr-xr-x  10 username  1177235957  340 Jul 18 15:41 ./
1020189 drwxr-xr-x  10 username  1177235957  340 Jul 18 15:16 ../
8004467 drwxr-xr-x  12 username  1177235957  408 Jul 18 15:16 .git/
8004528 -rw-r--r--   1 username  1177235957  501 Jul 18 15:16 .gitignore
8004919 lrwxr-xr-x   1 username  1177235957   22 Jul 18 15:41 Dependencies -> ../../lmi/Dependencies

então ../Dependencies , de acordo com o comando ls, é um link simbólico, no entanto:

bash-3.2$ test -L ../Dependencies
bash-3.2$ echo $?
0
bash-3.2$ test -h ../Dependencies
bash-3.2$ echo $?
0

Os dois não devem retornar 1? Eu estou entendendo mal algo sobre como isso deve funcionar? Como posso realizar meu objetivo, que é detectar se um arquivo é um link simbólico apontando para um diretório?

    
por Tamás Szelei 18.07.2016 / 15:58

3 respostas

3

Os valores de saída de sua experiência estão corretos. Quando o utilitário test avaliar uma expressão, se a expressão for avaliada como verdadeira, test retornará um status de saída zero (true) ; caso contrário, retorna 1 (false) .

Assim, no seu exemplo, test -L ../Dependencies retorna 0 (verdadeiro) porque ../Dependencies é um link simbólico. Se ../Dependencies não fosse um link simbólico, test retornaria 1 (false).

A instrução if do script de shell está correta, mas você pode adicionar comandos echo para ver se há outros problemas quando o script de shell é executado. Por exemplo, você pode adicionar dois comandos echo antes da instrução if :

echo "path is '$PWD'"
echo "out_dir is '$out_dir'"
    
por 18.07.2016 / 17:21
2

Eu escolheria uma solução mais complicada (já que isso combina com a minha personalidade, mas isso não é importante agora ...)

for x in $(ls -lp|egrep ^[dl].*\/$); do 
   case $(echo $x|cut -c 1) in 
      "d") echo "This is a dir";; 
      "l") echo "This is a link";;
   esac
done

Resumidamente, ls -lp imprime um formato longo com uma barra final para todos os diretórios. O primeiro caractere de formato longo nos informa o modo ( d para diretórios, l para link, - para arquivos regulares, etc). Dadas essas informações, podemos usar egrep para filtrar nosso ls para listagens de diretórios e links que terminam em / e usam case para filtrar ainda mais nossa lista. Nota: Esse loop também filtrará os arquivos vinculados devido à opção -p em ls

    
por 19.07.2016 / 08:49
1

Acabei com a seguinte solução:

function is_sym_link()
{
    readlink $1 > /dev/null
    return $?
}

Pode não cobrir todos os casos, mas para o meu ambiente é suficiente. Eu não sei porque o original não funcionou, infelizmente.

    
por 19.07.2016 / 12:37