ln -s с путем относительно pwd

26

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

ln -s /Users/niels/something/foo ~/bin/foo_link

пока это

cd /Users/niels/something
ln -s foo ~/bin/foo_link

не является.

Я считаю, что это как-то связано с foo_linkссылками на foo /Users/niels/binвместо/Users/niels/something

Итак, вопрос в том, как мне создать символическую ссылку, которая указывает на абсолютный путь, не вводя его на самом деле?

Для справки я использую Mac OS X 10.9 и Zsh.

Нильс Б.
источник

Ответы:

33

Самый простой способ связать текущий каталог как абсолютный путь, не набирая всю строку пути, был бы

ln -s "$(pwd)/foo" ~/bin/foo_link

target(Первый) аргумент для ln -sкоманды работает относительно местоположения символической ссылки, а не в текущем каталоге. Это помогает узнать, что, по сути, созданная символическая ссылка (второй аргумент) просто содержит текст , предоставленный вами для первого аргумента.

Поэтому, если вы делаете следующее:

cd some_directory
ln -s foo foo_link

а затем переместить эту ссылку вокруг

mv foo_link ../some_other_directory
ls -l ../some_other_directory

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

ln -s ../foo yet_another_link

а затем перейдите yet_another_linkв другой каталог и проверьте, куда он указывает, вы увидите, что он всегда указывает на ../foo. Это предполагаемое поведение, поскольку символические ссылки часто могут быть частью структуры каталогов, которые могут находиться в различных абсолютных путях.

В вашем случае, когда вы создаете ссылку, набрав

ln -s foo ~/bin/foo_link

foo_linkпросто содержит ссылку foo, относительно его местоположения. Помещение $(pwd)перед именем целевого аргумента просто добавляет абсолютный путь к текущему рабочему каталогу, так что ссылка создается с абсолютной целью.

Ахиллеас
источник
«... помогает представить, что созданная символическая ссылка просто содержит текст ...» Разве это не буквальная правда?
Wildcard
1
Это. Возможно, я мог бы изменить воображение, чтобы «знать» или «понимать».
Ахиллеас
Возможно, я запутался (снова). Кажется, когда вы говорите «цель», вы имеете в виду «источник». source_file(Первый) аргумент где ссылка указует, что дословно то , что вы входите в команде. target_file(Второй) аргумент становится именем ссылки , если то , что вы вводите не является каталогом, и в этом случае имя ссылки совпадает с базовым именем , source_fileно помещены в каталоге target_file.
Чарли
Ты прав, ̶ ̶t̶h̶e̶r̶e̶'̶s̶ ошибку в ̶a̶n̶s̶w̶e̶r̶.̶ CRAZY , как она ̶d̶i̶d̶n̶'̶t̶ пойманы ̶s̶o̶o̶n̶e̶r̶.̶ ̶F̶i̶x̶i̶n̶g̶.̶ Нет, ответ был прав. К lnстраница руководства, targetявляется первым аргументом (где ссылка указывает на ) , тогда как второй аргумент просто упоминается как link( sourceне упоминается).
Ахиллеас
3
В linux (gnu ln) страница man вызывает первый аргумент targetи второй link( man7.org/linux/man-pages/man1/ln.1.html ). Но в BSD (включая OS X) первый называется, sourceа второй target( freebsd.org/cgi/man.cgi?ln ). Весьма запутанно.
Кристопер
5

Использование флага -r( --relative) сделает эту работу:

ln -sr foo ~/bin/foo_link
Geremia
источник
4
Остерегайтесь, что -rэто GNUism, т.е. не POSIX, поэтому не будет работать в случае OP, так как стандартная lnкоманда OS X основана на BSD.
Jlliagre
2

Чтобы сохранить набор текста, вы можете сделать

ln -s "$PWD"/foo ~/bin/foo_link
косинус
источник
@ Фредди, это зависит от оболочки. В рыбе или зше это было бы нормально. В Bourne-подобных оболочках, включая bash и со значением по умолчанию $ IFS, SPC действительно будет проблемой, но также TAB, NL и все символы-заглушки (по крайней мере *, ?и [...]).
Стефан Шазелас
@ StéphaneChazelas Да, вы правы, и вопрос помечен bash, так что это хорошая идея - процитировать его. Мой плохой, я должен был быть более конкретным.
Фредди
0

Как насчет:

 $ cd /Users/niels/something
 $ ln -s ./foo ~/bin/foo_link
ptierno
источник
1
Нет, не делает трюк.
Нильс Б.