Symlink aliasing file in sottodirectory senza cambiare la directory corrente


11

Sembra che dovrebbe essere semplice collegare un file a un nuovo file in una sottodirectory .... .... senza spostare le sottodirectory. Ma qualcosa nella sintassi è sconcertante e contrario a quello che mi aspetterei. Ecco un caso di prova:

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

Questo crea solo un link simbolico rotto! Sto eseguendo questo in uno script di installazione dell'ambiente di compilazione, quindi voglio evitare di cambiare la directory di lavoro corrente, se possibile.

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

Inoltre, non funziona perché crea il collegamento simbolico nella directory temporanea anziché nella sottodirectory deploy.

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

Funziona, ma preferirei sapere come farlo senza cambiare directory.

Utilizzando un percorso completo come:

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

Funziona, ma non è pesante e in qualche modo poco pratico, specialmente in un ambiente di build in cui tutte le cose del progetto potrebbero essere diverse tra build e simili.

Come posso creare un collegamento simbolico tra due file in una sottodirectory, senza spostarmi in quella sottodirectory e fuori da essa, e dando al nuovo file "alias" un nuovo nome?

Risposte:


10

Ma qualcosa nella sintassi è sconcertante e contrario a quello che mi aspetterei.

Gli argomenti per ln, nella forma in cui lo stai usando, sono:

ln [OPTION] ... [-T] TARGET LINK_NAME (1 ° modulo)

La cosa sconcertante e non intuitiva è che quando si crea un collegamento simbolico, l' argomento target per lnnon è previsto che sia un percorso di un file, ma piuttosto il contenuto del collegamento simbolico da creare. Se ci pensate per un momento, è ovvio che deve essere così. Prendere in considerazione:

$ 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

In quell'esempio creo 2 symlink, chiamati "bar1" e "bar2", che puntano allo stesso file. lsmostra che i collegamenti simbolici stessi hanno contenuti diversi, tuttavia: uno contiene un percorso assoluto e uno contiene un percorso relativo. Per questo motivo, uno continuerebbe a funzionare anche se fosse spostato in un'altra directory e l'altro no:

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

Pertanto, considerando che dobbiamo essere in grado di creare collegamenti simbolici relativi e assoluti e persino di creare collegamenti simbolici rotti che non verranno interrotti se il file di destinazione viene successivamente creato, l' argomento di destinazione deve essere interpretato come testo a mano libera, piuttosto che percorso di un file già esistente.

Se si desidera creare un file denominato deploy / resources.php che si collega a deploy / resources.build.php, è necessario decidere se si desidera creare un collegamento simbolico assoluto (che è resiliente rispetto al collegamento simbolico spostato, ma si interrompe se il target viene spostato) o un collegamento simbolico relativo (che continuerà a funzionare fintanto che sia il collegamento simbolico che il bersaglio vengono spostati insieme e mantengono gli stessi percorsi relativi).

Per creare un link simbolico assoluto, puoi fare:

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

Per crearne uno relativo, devi prima capire il percorso relativo dalla sorgente alla destinazione. In questo caso, poiché l'origine e la destinazione sono nella stessa directory l'una rispetto all'altra, puoi semplicemente fare:

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

Se non fossero nella stessa directory, dovresti invece fare qualcosa del tipo:

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

In tal caso, anche se fooe barsono entrambi nella directory corrente, è necessario includere a ../nella ln destinazione perché descrive come trovare fdalla directory che contiene b.

Questa è una spiegazione estremamente lunga, ma speriamo che ti aiuti a capire lnun po 'meglio la sintassi.


3

È possibile creare il collegamento in una subshell, come segue:

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

Quando la subshell termina l'esecuzione, ti ritroverai ancora nella directory corretta.

In alternativa, puoi provare

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

che funziona anche, trascurando di includere nella CL il fatto che il file resources.build.php non si trova nella directory in cui si sta eseguendo il comando, ma si trova all'interno ./deploy .


Questa è magia nera, signore!
Kzqai,

1

Questo mi ha confuso fino a quando ho capito che un link simbolico è fondamentalmente un file di configurazione. cioè come scriverei i dati di quel percorso in un semplice file di testo:

ln -s [target] [link name]

diventa:

echo [target] > [link name]

L'errore che io (e probabilmente OP) stavo facendo è nel pensare ln necessità di conoscere il file che si rivolge. ln non se ne cura. Sta solo scrivendo alcune informazioni sul percorso in un file. Questo è un comando ln perfettamente ragionevole :

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

Quindi:

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

produce un file simlink chiamato resources.phpnella ./deploycartella che fa riferimento al file resources.build.phpnella cartella ./deploy/deploy/.

È improbabile che tu voglia e fornisce un link errato (interrotto). Non c'è niente di sbagliato nel collegamento, se metti quel file lì allora il collegamento funziona. Tuttavia, (come sottolineato da altri) ciò che io e l'OP volevamo era:

ln -s resources.build.php deploy/resources.php
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.