Symlink aliasing files em subdiretórios sem alterar o diretório atual

9

Parece que deve ser simples vincular um arquivo a um novo arquivo em um subdiretório .... .... sem mover os subdiretórios. Mas algo sobre a sintaxe é desconcertante e contrário ao que eu esperaria. Aqui está um caso de teste:

mkdir temp
cd temp
mkdir deploy
echo "Contents of the build file!" > deploy/resources.build.php
ln -s deploy/resources.build.php deploy/resources.php
cat deploy/resources.php #bad symlink

Isso cria um link simbólico quebrado! Estou executando isso em um script de configuração do ambiente de construção, portanto, quero evitar alterar o diretório de trabalho atual, se possível.

ln -s deploy/resources.build.php resources.php
cat deploy/resources.php

Também não funciona porque cria o link simbólico no diretório temp em vez do subdiretório de implementação.

cd deploy
ln -s resources.build.php resources.php
cd ..

Isso funciona, mas eu prefiro saber como fazer isso sem alterar os diretórios.

Usando um caminho completo como:

/home/whatever/src/project/temp/stuff/temp/deploy/resources.build.php

Funciona, mas é pouco versátil e pouco prático, especialmente em um ambiente de desenvolvimento onde todas as coisas do projeto podem ser diferentes entre construções e coisas do tipo.

Como posso criar um link simbólico entre dois arquivos em um subdiretório, sem passar para esse subdiretório e sair dele, e dando ao novo arquivo "alias" um novo nome?

    
por Kzqai 29.12.2014 / 19:49

3 respostas

9

But something about the syntax is perplexing and counter to what I would expect.

Os argumentos para ln , na forma que você está usando, são:

ln [OPTION]... [-T] TARGET LINK_NAME (1st form)

A coisa desconcertante e não intuitiva é que, quando você está criando um link simbólico, não é esperado que o argumento destino para ln seja um caminho para um arquivo, mas sim o conteúdo do arquivo. link simbólico a ser criado. Se você pensar por um momento, é óbvio que tem que ser assim. Considere:

$ echo foo >foo
$ ln -s foo bar1
$ ln -s $PWD/foo bar2
$ cat bar1
foo
$ cat bar2
foo
$ ls -l bar1 bar2
lrwxrwxrwx 1 matt matt  3 Dec 29 16:29 bar1 -> foo
lrwxrwxrwx 1 matt matt 29 Dec 29 16:29 bar2 -> /home/matt/testdir/foo

Nesse exemplo, eu crio 2 links simbólicos, chamados "bar1" e "bar2", que apontam para o mesmo arquivo. ls mostra que os próprios links simbólicos têm conteúdos diferentes - um contém um caminho absoluto e um contém um caminho relativo. Por causa disso, a pessoa continuaria trabalhando mesmo se fosse movida para outro diretório e a outra não:

$ mv bar2 /tmp
$ cat /tmp/bar2
foo
$ mv bar1 /tmp
$ cat /tmp/bar1
cat: /tmp/bar1: No such file or directory

Então, considerando que devemos ser capazes de fazer links simbólicos relativos e absolutos, e até mesmo criar links simbólicos quebrados que serão un-broken se o arquivo de destino for criado posteriormente, o argumento target tem para ser interpretado como texto livre, em vez do caminho para um arquivo já existente.

Se você quiser criar um arquivo chamado deploy / resources.php com links para deploy / resources.build.php, você precisa decidir se deseja criar um symlink absoluto (que é resiliente contra o link simbólico que está sendo movido, mas quebra se o alvo for movido), ou um link simbólico relativo (que continuará trabalhando enquanto o link simbólico e o alvo forem movidos juntos e mantiverem os mesmos caminhos relativos).

Para criar um symlink absoluto, você pode fazer:

$ ln -s $PWD/deploy/resources.build.php deploy/resources.php

Para criar um parente, você primeiro descobrirá o caminho relativo da origem para o destino. Nesse caso, como a origem e o destino estão no mesmo diretório em relação um ao outro, você pode simplesmente fazer:

$ ln -s resources.build.php deploy/resources.php

Se eles não estivessem no mesmo diretório, você precisaria fazer algo como:

$ ln -s ../foo/f bar/b

Nesse caso, mesmo que foo e bar estejam no diretório atual, você precisa incluir um ../ no ln destino porque descreve como localizar f do diretório que contém b .

Essa é uma explicação extremamente longa, mas esperamos que ajude você a entender a sintaxe ln um pouco melhor.

    
por 29.12.2014 / 22:49
3

Você pode criar o link em um subshell, da seguinte maneira:

  (cd deploy && ln -s resources.build.php resources.php && cat resources.php)

Quando o subshell termina a execução, você ainda estará no diretório correto.

Como alternativa, você pode tentar

 ln -s resources.build.php deploy/resources.php

que também funciona, negligenciando incluir no CL o fato de que o arquivo resources.build.php não está no diretório onde você está emitindo o comando, mas está de fato dentro ./deploy .

    
por 29.12.2014 / 20:05
1

Isso me confundiu até que percebi que um link simbólico é basicamente um arquivo de configuração. ou seja, como eu escreveria os dados desse caminho em um arquivo de texto simples:

ln -s [target] [link name]

torna-se:

echo [target] > [link name]

O erro que eu (e provavelmente OP) estava cometendo está em pensar que ln precisa saber sobre o arquivo que ele está mirando. ln não se importa. Está apenas escrevendo algumas informações de caminho em um arquivo. Este é um comando ln perfeitamente razoável:

ln -s /path/doesnt/exist/file.err
ll
file.err -> /path/doesnt/exist/file.err

Por isso:

ln -s deploy/resources.build.php deploy/resources.php

produz um arquivo simlink chamado resources.php na pasta ./deploy que está fazendo referência ao arquivo resources.build.php na pasta ./deploy/deploy/ .

Isso é improvável o que você quer e dá um link ruim (quebrado). Não há nada de errado com o link, se você colocar esse arquivo lá, então o link funciona. No entanto, (como apontado por outros) o que eu e o OP queríamos era:

ln -s resources.build.php deploy/resources.php
    
por 06.04.2018 / 16:36