Symlink псевдонимы файлов в подкаталогах без изменения текущего каталога

11

Похоже, что просто вставить символическую ссылку одного файла в новый файл в подкаталоге .... .... без перемещения подкаталогов. Но что-то в синтаксисе вызывает недоумение и противоречит тому, что я ожидал. Вот контрольный пример:

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

Это просто создает битую символическую ссылку! Я запускаю это в скрипте установки среды сборки, поэтому я хочу избежать изменения текущего рабочего каталога, если это возможно.

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

Также не работает, потому что он создает символическую ссылку во временном каталоге вместо подкаталога deploy.

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

Это работает, но я бы предпочел знать, как это сделать, не меняя каталоги.

Используя полный путь как:

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

Работает, но неудобно и несколько непрактично, особенно в среде сборки, где все компоненты проекта могут быть разными в разных сборках и тому подобное.

Как я могу создать символическую ссылку между двумя файлами в подкаталоге, не перемещаясь в этот подкаталог и не выходя из него, и в то же время давая новому файлу "псевдоним" новое имя?

Kzqai
источник

Ответы:

10

Но что-то в синтаксисе вызывает недоумение и противоречит тому, что я ожидал.

Аргументы lnв той форме, которую вы используете:

ln [ОПЦИЯ] ... [-T] TARGET LINK_NAME (1-я форма)

Недоумение и неясность в том, что когда вы создаете символическую ссылку, целевой аргумент lnне должен быть путем к файлу, а скорее содержимым символической ссылки, которая будет создана. Если вы подумаете об этом на мгновение, очевидно, что так и должно быть. Рассматривать:

$ 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

В этом примере я создаю 2 символические ссылки с именами «bar1» и «bar2», которые указывают на один и тот же файл. lsпоказывает, что сами символические ссылки имеют разное содержимое, хотя одна содержит абсолютный путь, а другая - относительный путь. Из-за этого один будет продолжать работать, даже если он будет перемещен в другой каталог, а другой - нет:

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

Таким образом, учитывая, что мы должны иметь возможность создавать как относительные, так и абсолютные символические ссылки, и даже создавать неработающие символические ссылки, которые станут неразрывными при последующем создании целевого файла, целевой аргумент должен интерпретироваться как текст произвольной формы, а не как путь к уже существующему файлу.

Если вы хотите создать файл с именем deploy / resources.php, который ссылается на deploy / resources.build.php, вам необходимо решить, хотите ли вы создать абсолютную символическую ссылку (которая устойчива к перемещаемой символической ссылке, но ломается, если цель перемещена) или относительная символическая ссылка (которая будет работать до тех пор, пока символическая ссылка и цель перемещаются вместе и поддерживают одинаковые относительные пути).

Чтобы создать абсолютную символическую ссылку, вы можете сделать:

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

Чтобы создать относительный, вы сначала должны определить относительный путь от источника к цели. В этом случае, поскольку источник и цель находятся в одном каталоге относительно друг друга, вы можете просто сделать:

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

Если бы они не были в одном каталоге, вам нужно было бы сделать что-то вроде:

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

В этом случае, даже если fooи barнаходятся в текущем каталоге, вы должны включать в себя ../в ln цель , потому что он описывает , как найти fиз каталога , содержащего b.

Это очень длинное объяснение, но, надеюсь, оно поможет вам лучше понять lnсинтаксис.

godlygeek
источник
3

Вы можете создать ссылку в подоболочке следующим образом:

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

Когда subshell завершит выполнение, вы окажетесь в правильном каталоге.

В качестве альтернативы вы можете попробовать

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

это также работает, игнорируя включение в CL того факта, что файл resources.build.php находится не в каталоге, в котором вы вводите команду, а на самом деле внутри ./deploy .

MariusMatutiae
источник
Это черная магия, сэр!
Kzqai
1

Это смущало меня, пока я не понял, что символическая ссылка - это в основном файл конфигурации т.е. как бы я записал эти данные пути в простой текстовый файл:

ln -s [target] [link name]

будет выглядеть так:

echo [target] > [link name]

Ошибка , что я (и , вероятно , OP) делал это в размышлении ¯Ln потребности знать о файле его ориентации. Мне все равно. Это просто запись некоторой информации о пути в файл. Это вполне разумно пер команда:

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

Следовательно:

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

создает файл simlink, вызываемый resources.phpв ./deployпапке, которая ссылается на файл resources.build.phpв папке ./deploy/deploy/.

Это маловероятно, что вы хотите, и дает плохую (неработающую) ссылку. В ссылке нет ничего плохого, если вы поместите этот файл туда, ссылка будет работать. Однако (как указали другие) я и ФП хотели:

ln -s resources.build.php deploy/resources.php
Мартин
источник