Que comando idempotente posso usar para fazer um link simbólico apontando para um diretório?

13

Eu quero colocar um comando em um script de shell que irá criar um link simbólico para o diretório, mas este script pode ser executado repetidamente, portanto, em chamadas subseqüentes, o comando não deve mudar nada.

Aqui está a estrutura do diretório:

% tree /tmp/test_symlink 
/tmp/test_symlink
├── foo
└── repo
    └── resources
        └── snippets
            ├── php.snippets
            ├── sh.snippets
            ├── snippets.snippets
            ├── sql.snippets
            └── vim.snippets

Eu quero criar um symlink em foo/ chamado trechos que aponta para o diretório /tmp/test_symlink/repo/resources/snippets .
Então eu corro:

% ln -sfv /tmp/test_symlink/repo/resources/snippets /tmp/test_symlink/foo/snippets
'/tmp/test_symlink/foo/snippets' -> '/tmp/test_symlink/repo/resources/snippets'

que dá o resultado desejado.

% tree /tmp/test_symlink                                                          
/tmp/test_symlink
├── foo
│   └── snippets -> /tmp/test_symlink/repo/resources/snippets
└── repo
    └── resources
        └── snippets
            ├── php.snippets
            ├── sh.snippets
            ├── snippets.snippets
            ├── sql.snippets
            └── vim.snippets

5 diretórios, 5 arquivos

No entanto, quando o comando é executado novamente,

% ln -sfv /tmp/test_symlink/repo/resources/snippets /tmp/test_symlink/foo/snippets
'/tmp/test_symlink/foo/snippets/snippets' -> '/tmp/test_symlink/repo/resources/snippets'

cria um link simbólico para um diretório, onde o link simbólico já existe coloca o symlink dentro do diretório real

% tree /tmp/test_symlink                                                          
/tmp/test_symlink
├── foo
│   └── snippets -> /tmp/test_symlink/repo/resources/snippets
└── repo
    └── resources
        └── snippets
            ├── php.snippets
            ├── sh.snippets
            ├── snippets -> /tmp/test_symlink/repo/resources/snippets
            ├── snippets.snippets
            ├── sql.snippets
            └── vim.snippets

por que isso está acontecendo e como posso modificar o comando para que invocações subseqüentes não criem esse efeito estranho?

    
por the_velour_fog 01.04.2017 / 07:40

2 respostas

14

Você deve usar a opção -T para isso, ele diz ln para sempre tratar o nome do link como o nome do link desejado, nunca como um diretório.

Sem essa opção, se você der a ln um nome de link que existe como um diretório, ele criará um novo link para o destino dentro desse diretório.

Note que -T é um GNU-ismo (pelo menos, não é em POSIX), mas você já está usando -v que também é um GNU-ismo, então imagino que não seja um problema.

Alternativamente, você pode apenas especificar o diretório pai como o nome do link, e o link sempre será (re) criado lá:

ln -sfv /tmp/test_symlink/repo/resources/snippets /tmp/test_symlink/foo/

Isso funciona porque o seu link simbólico tem o mesmo nome que o alvo.

    
por 01.04.2017 / 08:45
-1

Melhor eu posso dizer que o que está acontecendo aqui é que na segunda passagem o comando ln se comporta como cp ou mv , ou seja, se ele vir um "diretório" em < destination > colocará o arquivo dentro dele, caso contrário, < destination > não existe, isso fará com que < destination & gt ;. (que é o que o truque "slashdot" evita - isto é, garante que o < destination > existe e é um diretório).
Mas eu posso estar errado.

Em ambos os casos, isso parece funcionar

ln -sfv --no-dereference /tmp/test_symlink/repo/resources/snippets/ foo/snippets
    
por 01.04.2017 / 08:40