Enlace simbólico alias de archivos en subdirectorios sin cambiar el directorio actual

11

Parece que debería ser simple vincular un archivo a un nuevo archivo en un subdirectorio .... .... sin mover subdirectorios. Pero algo acerca de la sintaxis es desconcertante y contrario a lo que esperaría. Aquí hay un caso de prueba:

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

¡Esto solo crea un enlace simbólico roto! Estoy ejecutando esto en un script de configuración del entorno de compilación, por lo que quiero evitar cambiar el directorio de trabajo actual si es posible.

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

Tampoco funciona porque crea el enlace simbólico en el directorio temporal en lugar del subdirectorio de implementación.

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

Esto funciona, pero preferiría saber cómo hacerlo sin cambiar los directorios.

Usando una ruta completa como:

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

Funciona, pero es poco práctico y poco práctico, especialmente en un entorno de compilación donde todas las cosas del proyecto pueden ser diferentes entre compilaciones y similares.

¿Cómo puedo crear un enlace simbólico entre dos archivos en un subdirectorio, sin pasar a ese subdirectorio y fuera de él, y al mismo tiempo darle un nuevo nombre al "alias" del nuevo archivo?

Kzqai
fuente

Respuestas:

10

Pero algo acerca de la sintaxis es desconcertante y contrario a lo que esperaría.

Los argumentos para ln, en la forma en que lo está utilizando, son:

En [OPCIÓN] ... [-T] TARGET LINK_NAME (1er formulario)

Lo desconcertante y poco intuitivo es que cuando se crea un enlace simbólico, no se espera que el argumento objetivoln sea ​​una ruta a un archivo, sino el contenido del enlace simbólico que se creará. Si lo piensas por un momento, es obvio que tiene que ser así. 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

En ese ejemplo, creo 2 enlaces simbólicos, llamados "bar1" y "bar2", que apuntan al mismo archivo. lsmuestra que los enlaces simbólicos tienen contenidos diferentes, sin embargo, uno contiene una ruta absoluta y otra contiene una ruta relativa. Debido a esto, uno continuaría trabajando incluso si se moviera a otro directorio, y el otro no:

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

Entonces, teniendo en cuenta que debemos ser capaces de crear enlaces simbólicos tanto relativos como absolutos, e incluso crear enlaces simbólicos rotos que no se rompan si el archivo de destino se crea más adelante, el argumento de destino debe interpretarse como texto de forma libre, en lugar de ruta a un archivo ya existente.

Si desea crear un archivo llamado deploy / resources.php que se vincule a deploy / resources.build.php, debe decidir si desea crear un enlace simbólico absoluto (que es resistente al enlace simbólico que se está moviendo, pero se rompe si el el objetivo se mueve) o un enlace simbólico relativo (que seguirá funcionando siempre que el enlace simbólico y el objetivo se muevan juntos y mantengan las mismas rutas relativas).

Para crear un enlace simbólico absoluto, puede hacer lo siguiente:

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

Para crear uno relativo, primero debe averiguar la ruta relativa desde el origen hasta el destino. En este caso, dado que el origen y el destino están en el mismo directorio uno con respecto al otro, puede hacer lo siguiente:

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

Si no estuvieran en el mismo directorio, necesitaría hacer algo como:

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

En ese caso, a pesar de que fooy barson a la vez en el directorio actual, es necesario incluir una ../en el ln objetivo , ya que describe cómo encontrar fdesde el directorio que contiene b.

Esa es una explicación extremadamente larga, pero espero que te ayude a entender la lnsintaxis un poco mejor.

Godlygeek
fuente
3

Puede crear el enlace en una subshell, de la siguiente manera:

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

Cuando el subshell finalice la ejecución, te encontrarás en el directorio correcto.

Alternativamente, puedes intentar

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

que también funciona, sin incluir en el CL el hecho de que el archivo resources.build.php no está en el directorio donde está emitiendo el comando, sino que está dentro de ./deploy .

MariusMatutiae
fuente
¡Esto es magia negra, señor!
Kzqai
1

Esto me confundió hasta que me di cuenta de que un enlace simbólico es básicamente un archivo de configuración. es decir, cómo escribiría esos datos de ruta en un archivo de texto simple:

ln -s [target] [link name]

se convierte en:

echo [target] > [link name]

El error que yo (y probablemente OP) estaba haciendo es pensar en ln necesita saber sobre el archivo que está proyectando. En no le importa. Es solo escribir información de ruta en un archivo. Este es un comando ln perfectamente razonable :

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

Por lo tanto:

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

produce un archivo simlink llamado resources.phpen la ./deploycarpeta que hace referencia al archivo resources.build.phpen la carpeta ./deploy/deploy/.

Es poco probable lo que quiere y le da un enlace malo (roto). No hay nada malo con el enlace, si pones ese archivo allí, entonces el enlace funciona. Sin embargo, (como lo señalaron otros) lo que yo y el OP queríamos era:

ln -s resources.build.php deploy/resources.php
Martín
fuente