Fichiers d'alias de liaison symbolique dans les sous-répertoires sans changer le répertoire courant

11

Il semble qu'il devrait être simple de lier symboliquement un fichier à un nouveau fichier dans un sous-répertoire .... .... sans déplacer les sous-répertoires. Mais quelque chose à propos de la syntaxe laisse perplexe et va à l'encontre de ce à quoi je m'attendrais. Voici un cas de test:

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

Cela crée juste un lien symbolique cassé! J'exécute cela dans un script de configuration de l'environnement de construction, donc je veux éviter de changer le répertoire de travail actuel si possible.

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

Ne fonctionne pas non plus car il crée le lien symbolique dans le répertoire temporaire au lieu du sous-répertoire deploy.

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

Cela fonctionne, mais je préfère savoir comment le faire sans changer de répertoire.

Utiliser un chemin complet comme:

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

Fonctionne, mais est peu pratique et quelque peu impraticable, en particulier dans un environnement de génération où tous les éléments du projet peuvent être différents entre les générations, etc.

Comment puis-je créer un lien symbolique entre deux fichiers dans un sous-répertoire, sans entrer dans ce sous-répertoire et en sortir, et tout en donnant au nouveau fichier "alias" un nouveau nom?

Kzqai
la source

Réponses:

10

Mais quelque chose à propos de la syntaxe laisse perplexe et va à l'encontre de ce à quoi je m'attendrais.

Les arguments pour ln, sous la forme que vous l'utilisez, sont:

Dans [OPTION] ... [-T] TARGET LINK_NAME (1er formulaire)

La chose déroutante et peu intuitive est que lorsque vous créez un lien symbolique, l' argument cibleln n'est pas censé être un chemin d'accès à un fichier, mais plutôt le contenu du lien symbolique à créer. Si vous y réfléchissez un instant, il est évident que cela doit être ainsi. Considérer:

$ 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

Dans cet exemple, je crée 2 liens symboliques, nommés "bar1" et "bar2", qui pointent vers le même fichier. lsmontre que les liens symboliques eux-mêmes ont un contenu différent, cependant - l'un contient un chemin absolu et l'autre contient un chemin relatif. Pour cette raison, l'un continuerait de fonctionner même s'il était déplacé vers un autre répertoire, et l'autre ne le ferait pas:

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

Donc, étant donné que nous devons être en mesure de créer des liens symboliques relatifs et absolus, et même de créer des liens symboliques rompus qui ne seront pas rompus si le fichier cible est créé ultérieurement, l' argument cible doit être interprété comme du texte de forme libre, plutôt que chemin vers un fichier déjà existant.

Si vous souhaitez créer un fichier nommé deploy / resources.php qui relie à deploy / resources.build.php, vous devez décider si vous souhaitez créer un lien symbolique absolu (qui résiste au lien symbolique déplacé, mais se casse si le cible est déplacée), ou un lien symbolique relatif (qui continuera de fonctionner tant que le lien symbolique et la cible sont déplacés ensemble et conservent les mêmes chemins relatifs).

Pour créer un lien symbolique absolu, vous pouvez faire:

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

Pour en créer un relatif, vous devez d'abord déterminer le chemin relatif de la source à la cible. Dans ce cas, puisque la source et la cible sont dans le même répertoire l'une par rapport à l'autre, vous pouvez simplement faire:

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

S'ils n'étaient pas dans le même répertoire, vous devriez plutôt faire quelque chose comme:

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

Dans ce cas, même si fooet se bartrouvent tous les deux dans votre répertoire actuel, vous devez inclure un ../dans la ln cible car il décrit comment rechercher fdans le répertoire contenant b.

C'est une explication extrêmement longue, mais j'espère qu'elle vous aidera à mieux comprendre la lnsyntaxe.

godlygeek
la source
3

Vous pouvez créer le lien dans un sous-shell, comme suit:

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

Lorsque le sous-shell termine l'exécution, vous vous retrouverez toujours dans le bon répertoire.

Vous pouvez également essayer

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

qui fonctionne également, en négligeant d'inclure dans le CL le fait que le fichier resources.build.php ne se trouve pas dans le répertoire où vous exécutez la commande, mais se trouve en fait dans ./deploy .

MariusMatutiae
la source
C'est de la magie noire, monsieur!
Kzqai
1

Cela m'a confondu jusqu'à ce que je réalise qu'un lien symbolique est essentiellement un fichier de configuration. c'est-à-dire comment pourrais-je écrire ces données de chemin dans un simple fichier texte:

ln -s [target] [link name]

devient:

echo [target] > [link name]

L'erreur que je (et probablement OP) faisais est de penser que ln a besoin de connaître le fichier qu'il cible. Ça m'est égal. Il suffit d'écrire des informations de chemin dans un fichier. C'est une commande ln parfaitement raisonnable :

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

Par conséquent:

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

produit un fichier simlink appelé resources.phpdans le ./deploydossier qui fait référence au fichier resources.build.phpdans le dossier ./deploy/deploy/.

C'est peu probable ce que vous voulez et donne un mauvais lien (cassé). Il n'y a rien de mal avec le lien, si vous mettez ce fichier là, alors le lien fonctionne. Cependant, (comme l'ont souligné d'autres), ce que moi et le PO voulions était:

ln -s resources.build.php deploy/resources.php
Martin
la source