Pliki aliasingu dowiązań symbolicznych w podkatalogach bez zmiany bieżącego katalogu

11

Wygląda na to, że powinno być proste dowiązanie jednego pliku do nowego pliku w podkatalogu .... .... bez przenoszenia podkatalogów. Ale coś w składni jest kłopotliwe i sprzeczne z tym, czego bym się spodziewał. Oto przypadek testowy:

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

To po prostu tworzy uszkodzony link symboliczny! Korzystam z tego w skrypcie instalacyjnym środowiska kompilacji, więc chcę w miarę możliwości unikać zmieniania bieżącego katalogu roboczego.

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

Nie działa również, ponieważ tworzy dowiązanie symboliczne w katalogu temp zamiast podkatalogu wdrażania.

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

To działa, ale wolałbym wiedzieć, jak to zrobić bez zmiany katalogów.

Korzystanie z pełnej ścieżki, takiej jak:

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

Działa, ale jest niewygodny i nieco niepraktyczny, szczególnie w środowisku kompilacji, w którym wszystkie elementy projektu mogą się różnić między kompilacjami i tym podobne.

Jak mogę utworzyć dowiązanie symboliczne między dwoma plikami w podkatalogu, bez przechodzenia do tego podkatalogu i poza nim, a jednocześnie nadając nowemu plikowi „alias” nową nazwę?

Kzqai
źródło

Odpowiedzi:

10

Ale coś w składni jest kłopotliwe i sprzeczne z tym, czego bym się spodziewał.

Argumenty przemawiające za lntym, że używasz go, to:

W [OPCJA] ... [-T] TARGET LINK_NAME (1. formularz)

Niepokojące, nieintuicyjne jest to, że podczas tworzenia dowiązania symbolicznego nie oczekuje się , że argumentem docelowymln będzie ścieżka do pliku, a raczej zawartość dowiązania symbolicznego, które ma zostać utworzone. Jeśli pomyślisz o tym przez chwilę, to oczywiste, że tak musi być. Rozważać:

$ 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

W tym przykładzie tworzę 2 dowiązania symboliczne o nazwach „bar1” i „bar2”, które wskazują ten sam plik. lspokazuje, że same dowiązania symboliczne mają jednak inną zawartość - jedna zawiera ścieżkę bezwzględną, a druga ścieżkę względną. Z tego powodu jeden kontynuowałby pracę, nawet gdyby został przeniesiony do innego katalogu, a drugi nie:

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

Biorąc pod uwagę, że musimy być w stanie tworzyć zarówno względne, jak i bezwzględne dowiązania symboliczne, a nawet tworzyć uszkodzone dowiązania symboliczne, które staną się niezniszczone, jeśli plik docelowy zostanie później utworzony, argument docelowy należy interpretować jako tekst dowolny, a nie ścieżka do już istniejącego pliku.

Jeśli chcesz utworzyć plik o nazwie deploy / resources.php, który prowadzi do obrazu deploy / resources.build.php, musisz zdecydować, czy chcesz utworzyć bezwzględne dowiązanie symboliczne (które jest odporne na przenoszone dowiązanie symboliczne, ale pęka, jeśli cel został przeniesiony) lub względne dowiązanie symboliczne (które będzie działać tak długo, jak dowiązanie symboliczne i cel zostaną przeniesione razem i utrzymają te same ścieżki względne).

Aby utworzyć absolutne dowiązanie symboliczne, możesz:

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

Aby utworzyć względną, najpierw musisz obliczyć ścieżkę względną od źródła do celu. W takim przypadku, ponieważ źródło i cel znajdują się w tym samym katalogu względem siebie, możesz po prostu zrobić:

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

Jeśli nie znajdują się w tym samym katalogu, należy zamiast tego zrobić coś takiego:

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

W tym przypadku, chociaż fooi barto zarówno w bieżącym katalogu, trzeba obejmują ../w ln cel , ponieważ opisuje, jak znaleźć fw katalogu zawierającym b.

To bardzo długie wytłumaczenie, ale mam nadzieję, że pomoże ci to lepiej zrozumieć lnskładnię.

godlygeek
źródło
3

Możesz utworzyć łącze w podpowłoce w następujący sposób:

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

Kiedy podpowłoka zakończy wykonywanie, nadal będziesz znajdować się w odpowiednim katalogu.

Alternatywnie możesz spróbować

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

co również działa, pomijając dołączenie do CL faktu, że plik resources.build.php nie znajduje się w katalogu, w którym wydaje się polecenie, ale w rzeczywistości znajduje się w ./deploy .

MariusMatutiae
źródło
To jest czarna magia, proszę pana!
Kzqai
1

Zdezorientowało mnie to, dopóki nie zrozumiałem, że dowiązanie symboliczne jest w zasadzie plikiem konfiguracyjnym. tzn. jak zapisać te dane ścieżki do prostego pliku tekstowego:

ln -s [target] [link name]

staje się:

echo [target] > [link name]

Błąd, że ja (i prawdopodobnie OP) robił to w myśleniu ln musi wiedzieć o pliku jest ona kierowana. ln nie obchodzi. Po prostu zapisuje informacje o ścieżce do pliku. Jest to całkowicie rozsądne polecenie ln :

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

W związku z tym:

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

tworzy plik simlink wywoływany resources.phpw ./deployfolderze, który odwołuje się do pliku resources.build.phpw folderze ./deploy/deploy/.

Jest to mało prawdopodobne, co chcesz i daje zły (uszkodzony) link. Z linkiem nie ma nic złego, jeśli umieścisz tam ten plik, wówczas link będzie działał. Jednak (jak zauważyli inni) chciałem ja i OP:

ln -s resources.build.php deploy/resources.php
Jaskółka oknówka
źródło