Ligação simbólica de arquivos com alias em subdiretórios sem alterar o diretório atual

11

Parece que deve ser simples vincular um arquivo a um novo arquivo em um subdiretório .... .... sem mover 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 apenas cria um link simbólico quebrado! Estou executando isso em um script de configuração do ambiente de compilação, portanto, desejo 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 deploy.

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

Isso funciona, mas eu preferiria 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 é imprudente e um tanto impraticável, especialmente em um ambiente de construção em que todo o material do projeto pode ser diferente entre construções e similares.

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

Kzqai
fonte

Respostas:

10

Mas algo sobre a sintaxe é desconcertante e contrário ao que eu esperaria.

Os argumentos para ln, no formato que você está usando, são:

Em [OPTION] ... [-T] TARGET LINK_NAME (1º formulário)

O desconcertante e não intuitivo é que, ao criar um link simbólico, não se espera que o argumento de destinoln seja o caminho para um arquivo, mas o conteúdo do link simbólico a ser criado. Se você pensar por um momento, é óbvio que tem que ser assim. Considerar:

$ 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, crio 2 links simbólicos, chamados "bar1" e "bar2", que apontam para o mesmo arquivo. lsmostra que os links simbólicos possuem conteúdos diferentes - um contém um caminho absoluto e o outro contém um caminho relativo. Por isso, um continuaria trabalhando mesmo se fosse movido para outro diretório e o outro não:

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

Portanto, considerando que devemos ser capazes de criar links simbólicos relativos e absolutos, e até mesmo criar links simbólicos quebrados que não serão quebrados se o arquivo de destino for criado posteriormente, o argumento de destino deverá ser interpretado como texto de forma livre, em vez de caminho para um arquivo já existente.

Se você deseja criar um arquivo chamado deploy / resources.php vinculado a deploy / resources.build.php, decida se deseja criar um link simbólico absoluto (que seja resistente ao movimento do link simbólico, mas quebre se o o destino é movido) ou um link simbólico relativo (que continuará funcionando enquanto o link simbólico e o destino forem movidos juntos e mantiverem os mesmos caminhos relativos).

Para criar um link simbólico absoluto, você pode fazer:

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

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

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

Se eles não estivessem no mesmo diretório, seria necessário fazer algo como:

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

Nesse caso, mesmo que fooe barestão ambos em seu diretório atual, você precisa incluir um ../no ln alvo porque ele descreve como localizar fa partir do diretório que contém b.

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

godlygeek
fonte
3

Você pode criar o link em uma 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, deixando de incluir no CL o fato de que o arquivo resources.build.php não está no diretório em que você está emitindo o comando, mas está dentro de ./deploy .

MariusMatutiae
fonte
Isso é magia negra, senhor!
Kzqai
1

Isso me confundiu até eu perceber que um link simbólico é basicamente um arquivo de configuração. ou seja, como eu escreveria esses dados de 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 fazendo está em pensar ln precisa saber sobre o arquivo que tem como meta. ln não se importa. É só escrever algumas informações do 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

Conseqüentemente:

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

produz um arquivo simlink chamado resources.phpna ./deploypasta que está referenciando o arquivo resources.build.phpna pasta ./deploy/deploy/.

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

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