Linux: Kniha kouzel, vanilková příchuť 2.14 (15. července 2022)
Veškerá moc příkazové řádky/příkazového řádku přehledně, pro začátečníky i pokročilé

9. Pevné a symbolické odkazy

Řada 2.x vanilkové příchuti Linuxu: Knihy kouzel je od 15. července 2022 do 1. března 2025 ve stavu dlouhodobé pasivní údržby; nahlášené chyby budou opravovány, ale aktivní vývoj se již věnuje jiným projektům. Máte-li zájem pokračovat v tvorbě Linuxu: Knihy kouzel pro novější verze linuxových operačních systémů, kontaktujte autora nebo rovnou vytvořte odnož.

1. Úvod

Pevný odkaz je pojmenovaný odkaz na soubor z adresáře. Většina nelinuxových typů souborových systémů dovoluje mít na každý soubor pouze jeden pevný odkaz, takže umístění i pojmenování souboru je pak jednoznačné; linuxové souborové systémy vás ale takto omezují pouze v umísťování adresářů. Na každý soubor vám však dovolují zřídit až tisíce rovnocenných pevných odkazů, takže tentýž soubor se pak v souborovém systému nachází pod více názvy, případně i v různých adresářích a nezáleží na tom, přes který z těchto názvů k němu přistupujete. Zatímco všechny ostatní vlastnosti souboru jsou jednoznačně uloženy v jeho metadatech, název a příslušnost k adresáři určuje každý pevný odkaz samostatně. Pevné odkazy jsou (na rozdíl od symbolických) vždy platné, protože data a metadata souboru se nesmažou, dokud na ně nějaký pevný odkaz odkazuje.

Symbolický odkaz je něco docela jiného – je to malý zvláštní soubor, který obsahuje pouze určitou relativní či absolutní cestu a programy s ním pak většinou zachází tak, jako by se na daném místě nacházel soubor či adresář touto cestou odkazovaný – jde-li o adresář, můžeme do něj vstoupit příkazem „cd“; jde-li o spustitelný program, můžeme ho spustit atd. Pokud ovšem na odkazované cestě nic neleží, symbolický odkaz je neplatný a programy se s tím musejí nějak vyrovnat.

Příkazy ln, readlink, stat a některé další jsou vyvíjeny v rámci projektu GNU.

2. Definice

  • Pevný odkaz je, obecně vzato každá položka v adresáři; pro účely této kapitoly se však omezíme na definici, že pevným odkazem je pouze adresářová položka reprezentující obyčejný soubor. Součástí pevného odkazu je pouze název a umístění v adresáři, všechny ostatní údaje o souboru jsou vlastnostmi souboru jako takového.
  • Symbolický odkaz je malý zvláštní soubor, který obsahuje relativní či absolutní cestu k cílovému souboru či adresáři. Symbolické odkazy se dělí na absolutní (obsahující absolutní cestu) a relativní (obsahující relativní cestu). Symbolický odkaz odkazující na neexistující cestu se označuje jako neplatný.
  • Následovat symbolický odkaz (follow) znamená chovat se, jako by se na jeho místě a pod jeho názvem skutečně nacházel odkazovaný soubor či adresář. Oproti tomu nenásledovat symbolický odkaz znamená chovat se k němu jen jako k adresářové položce. V linuxu je obvyklé, že při práci s jednotlivým souborem či adresářem se symbolické odkazy následují (např. pokusíte-li se spustit symbolický odkaz na program, spustí se program), zatímco při rekurzivním průchodu adresářovou strukturou (např. příkazy „find“, „cp -R“, „chmod -R“ apod.) se nenásledují. Ve většině případů však toto chování můžete změnit určitým parametrem příkazu.

3. Zaklínadla

3/1 Pevné odkazy

@vytvořit pevný odkaz na soubor#1
ln -T[f][v] [--] cesta/k/souboru cesta/výsl/odkazu
@vytvořit pevné odkazy hromadně#2
ln -t[f][v] [--] cílový/adresář cesta/k/souboru
@přejmenovat či přesunout pevný odkaz (alternativy)#3
mv -T[i] původní/cesta nová/cesta
mv -T[f] původní/cesta nová/cesta
@smazat pevný odkaz#4
rm [--] cesta/k/odkazu
@vypsat počítadlo odkazů#5 (1)
stat -c %h [-L] [--] cesta-k-odkazu
@vypsat kanonickou (absolutní) cestu (bez/s následováním)#6
realpath -se cesta-k-odkazu⊨ /home/petr/odkaz-na-passwd
realpath -e cesta-k-odkazu⊨ /etc/passwd
@odkazují dva odkazy na tentýž soubor? (s následováním/bez něj)#7
test cesta1 -ef cesta2
test "$(stat -c %d/%i -L [--] cesta1 )" = "$(stat -c %d/%i -L [--] cesta2)"
@osamostatnit pevný odkaz od ostatních odkazů#8
f="název-souboru"
test "$(stat -L -c %h "$f")" -le 1 || if test -L "$f"; then ln -sfT "$(readlink -- "$1")"; elif test -f "$f"; then cp -Tai -- "$f" "${f}.nový" && mv -Tf -- "${f}.nový" "$f"; fi
@vypsat kanonickou cestu adresáře obsahujícího pevný odkaz (s následováním)#9
dirname -- "$(realpath -e cesta-k-odkazu)"⊨ /etc

3/2 Symbolické odkazy (vytvořit)

@vytvořit relativní/absolutní (bez následování)#1
ln -sT[f] "$(realpath -s "--relative-to=$(dirname [--] cesta/výsl/odkazu)" [--] cesta/k/cíli)" [--] cesta/výsl/odkazu
ln -sT[f] "$(realpath -s [--] cesta/k/cíli)" [--] cesta/výsl/odkazu
@vytvořit relativní/absolutní (s následováním)#2
ln -rsT[f] [--] cesta/k/cíli cesta/výsl/odkazu
ln -sT[f] "$(realpath -e [--] cesta/k/cíli)" [--] cesta/výsl/odkazu
@hromadné vytvoření relativních (s následováním)#3 (2)
ln -rs -t cílový/adresář [--] cesta/k/cíli
@vytvořit obecný#4 (3)
ln -sT[f] "obsah-odkazu" cesta/výsl/odkazu

3/3 Symbolické odkazy (ostatní operace)

@přejmenovat či přesunout (alternativy)#1 (4)
mv -T[i] původní/cesta nová/cesta
mv -T[f] původní/cesta nová/cesta
@smazat#2
rm [--] cesta/k/odkazu
@je adresářová položka symbolický odkaz?#3
test -L cesta/k/položce
@je absolutní/relativní?#4
[[ [-L cesta/k/odkazu &&] $(readlink [--] cesta/k/odkazu ) = /* ]]
[[ [-L cesta/k/odkazu &&] $(readlink [--] cesta/k/odkazu ) != /* ]]
@odkazuje na soubor/na adresář/na pojmenovanou rouru?#5
test [-L cesta/k/odkazu -a] -f cesta/k/odkazu
test [-L cesta/k/odkazu -a] -d cesta/k/odkazu
test [-L cesta/k/odkazu -a] -p cesta/k/odkazu
@je neplatný?#6 (5)
! readlink -e -- cesta/k/odkazu >/dev/null && test -L cesta/k/odkazu
@vypsat obsah (doslovně)#7
readlink [--] cesta/k/odkazu⊨ ../../etc/passwd
@vypsat kanonickou (absolutní) cestu cíle#8
realpath -e cesta-k-odkazu⊨ /etc/passwd
@nahradit symbolický odkaz pevným odkazem na tentýž soubor#9
ln -Tf[v] [--] "$(readlink -e cesta/k/odkazu)" "cesta/k/odkazu"

3/4 Rekurzivní operace

@okopírovat adresáře, ale na soubory místo kopírování vytvořit pevné odkazy#1
[sudo] cp -TRld[v] [--] původní/adresář nový/adresář
@kopírovat s následováním symbolických odkazů#2
[sudo] cp -TRL[v] [--] původní/adresář nový/adresář
@nahradit předponu v symbolických odkazech#3
find adresář -type l -printf '=%p\0=%l\0\0' | gawk -b -v "puv=co-nahradit" -v "nov=čím-nahradit" -v 'FS=\0' -v 'RS=\0\0' -v 'OFS=' -v apo=\' 'function f(s) {return gensub(apo, apo "\\" apo apo, "g", s)} substr($2, 2, length(puv)) == puv {print "ln -Tfsv ", apo, f(nov substr($2, 2 + length(puv))), apo, " ", apo, f(substr($1, 2)), apo}' | bash [-e]
@kde je to možné, konvertovat symbolické odkazy na pevné#4
find adresář -type l ! -xtype d,l -exec sh -c 'exec ln -Tfv -- "$(readlink -e -- "$1")" "$1"' -- '{}' \; [2>/dev/null]
@symbolické odkazy konvertovat na relativní/absolutní#5
find adresář -type l ! -xtype l -lname '/*' -exec ln -Trsf -- '{}' '{}' \;
find adresář -type l ! -xtype l ! -lname '/*' -exec sh -c 'exec ln -Tsf -- "$(readlink -e -- "$1")" ""' -- '{}' \;
@odstranit všechny symbolické odkazy#6
find adresář -type l [-print] -delete
@najít duplicitní soubory a sloučit je pomocí pevných odkazů#7

4. Parametry příkazů

4/1 ln

ln [parametry] [--] zdroj cíl
ln [parametry] -t cílový/adresář [--] zdroj
○ -s ◉Vytváří symbolické odkazy/pevné odkazy.
☐ -vVypíše každý vytvořený odkaz.
○ -f ○ -i ◉Pokud cíl existuje: přepíše ho bez ptaní/zeptá se uživatele/selže.
☐ -rV kombinaci s -s vytváří platné relativní symbolické odkazy. Výchozí chování: vytváří obecné symbolické odkazy.
☐ -PNenásleduje symbolické odkazy uvedené jako „zdroj“. Nemá smysl v kombinaci s „-s“.

4/2 readlink

readlink [parametry] [--] cesta
readlink -n [--] cesta
○ -e ◉Vypíše obsah jako kanonickou absolutní cestu (pokud cíl existuje)/tak, jak je.
○ -z ◉Jednotlivé obsahy ukončuje nulovým bajtem/znakem „\n“.
-nVypíše obsah symbolického odkazu bez dodatečného ukončovače.

5. Instalace na Ubuntu

Všechny použité nástroje jsou základní součástí Ubuntu přítomnou i v minimální instalaci. Výjimkou je jen příkaz „gawk“, který je nutno doinstalovat:

sudo apt-get install gawk

6. Ukázka

echo A1 >a; echo B1 >b
ln -Tv a c
stat -c %h a
echo A2 >a; cat c
mkdir o; ln -rsT a o/a
readlink -- o/a
readlink -e -- o/a
cat o/a
test a -ef c; echo $?
test a -ef o/a; echo $?
stat -c %h o/a
stat -c %h -L o/a
find o -type l -print -delete
rmdir -v o; rm -fv a b c

7. Tipy a zkušenosti

7/1 Zkušenosti s pevnými odkazy

  • Maximální počet pevných odkazů na jeden soubor je omezený souborovým systémem; v souborových systémech typu ext4 je to 65000, u btrfs 65535 a u tmpfs podstatně víc (podařilo se mi jich vytvořit i víc než milion, aniž by to spotřebovalo příliš mnoho paměti).
  • Soubor bude odstraněn z disku v momentě, kdy už na něj neexistují žádné pevné odkazy, není spuštěný jako proces a není otevřený žádným deskriptorem žádného procesu.
  • Přístupová práva brání uživatelům (kromě superuživatele) vytvářet pevné odkazy na cizí soubory (tzn. vlastněné jiným uživatelem), ledaže k nim mají práva čtení i zápisu („r“ a „w“).

7/2 Zkušenosti se symbolickými odkazy

  • Častou začátečnickou chybou je příkaz typu „ln -s soubory/a odkazy/na-a“. Uvedený příkaz totiž vytvoří symbolický odkaz s obsahem „soubory/a“ a relativní symbolické odkazy se vždy vyhodnocují relativně vůči adresáři, ve kterém se nacházejí, takže faktickým cílem vytvořeného odkazu bude ve skutečnosti „odkazy/soubory/a“, který nejspíš neexistuje. Proto při vytváření relativních symbolických odkazů vždy používejte parametr „-r“, který cesty automaticky opraví. (Toto se nijak netýká absolutních ani pevných odkazů.)
  • Méně častou začátečnickou chybou je příkaz typu „ln -sf /etc/passwd odkaz-na-passwd“. Pokud by se totiž stalo, že „odkaz-na-passwd“ je existující symbolický odkaz na adresář, příkaz „ln“ uváží, že chcete vytvořit odkaz uvnitř odkazovaného adresáře, ne že chcete přepsat existující symbolický odkaz. Proto v kombinaci s parametrem „-f“ vždy používejte také parametr „-T“, nebo „-t“. (Tyto parametry se může vyplatit používat i v ostatních případech.)
  • Pokud symbolický odkaz odkazuje někam dovnitř adresáře, kam uživatel nemá právo vstoupit, bude se odkaz jevit uživateli jako neplatný, i když to ve skutečnosti nebude pravda.
  • Symbolický odkaz má vlastnictví a skupinu, ale nemá vlastní přístupová práva. Přístup k odkazovanému souboru či adresáři se vždy řídí přístupovými právy odkazovaného souboru či adresáře.
  • Symbolický odkaz sám o sobě je „nezapisovatelný“; pokud ho chceme změnit, musíme ho nejprve smazat a pak znovu vytvořit. To také znamená, že ke změně obsahu symbolického odkazu potřebuje uživatel právo zápisu do adresáře, kde se odkaz nachází.
  • Symbolický odkaz může odkazovat na jiný symbolický odkaz, ale maximální počet zanoření symbolických odkazů je 40 (pravděpodobně jde změnit).
  • Maximální délka obsahu symbolického odkazu je 4095 bajtů.

7/3 Jaký typ odkazu zvolit?

Při rozhodování mezi absolutním a relativním symbolickým odkazem je zasadní otázka, zda se bude odkaz přesouvat společně s cílem, nebo samostatně.

Pokud se bude přesouvat spíše samostatně, je vhodnější absolutní symbolický odkaz, protože ten je možno volně přesouvat kamkoliv a stále bude odkazovat na stejný cíl. Tím pádem s ním i v grafických správcích souborů můžete zacházet víceméně jako se souborem samotným. Pokud by přece jen došlo k přesunutí či přejmenování cíle, je nutno všechny absolutní odkazy na cíl vyhledat a opravit.

Pokud se bude odkaz přesouvat spolu s cílem, což je typické pro „blízké“ odkazy a odkazy v rámci výměnných médií, je vhodnější relativní symbolický odkaz, protože ten v takových případech zůstane platný.

Pokud se bude přesouvat cíl, vytvořte zvláštní symbolický odkaz na adresář cíle a přes něj směrujte na cíl (bez následování) absolutní symbolické odkazy. Po přesunutí cíle pak bude stačit opravit pouze tento jeden odkaz a ostatní odkazy zůstanou platné beze změny.

Pevné odkazy se vyplácí spíš pro dočasné nebo technicky přesně vymezené účely, protože je u nich vždy riziko rozpojení a není snadné si toho všimnout. Většinou se rozpojí při kopírování, při ukládání do archivu nebo když nějaký program soubor smaže a ihned znovu vytvoří. Také se může stát, že původní soubor přejmenujete a místo něj vytvoříte pod původním názvem nový; v takovém případě zůstane pevný odkaz navázaný na původní soubor. K rozpojení také dojde, pokud soubor přesunete příkazem „mv“ přes hranici souborového systému a nazpět.

Asi nejužitečnější způsob využití pevných odkazů je, když příkazem „cp -Rld“ vytvoříte kopii adresářové struktury, v ní pak budete soubory volně přesouvat, mazat apod. a později s ní nahradíte původní adresářovou strukturu. Podobný postup můžete s určitými omezeními použít k napodobnení klonů pododdílů btrfs.

Pevné odkazy se také vyplatí pro různé dočasné účely, kdy mohou být jejich technické vlastnosti výhodné. Vždy je ale třeba mít na paměti riziko rozpojení.

8. Další zdroje informací

9. Zákulisí kapitoly

V této verzi kapitoly chybí:

  • nic

Tato kapitola záměrně nepokrývá:

  • nic
1 Parametr „-L“ vypne následování symbolických odkazů. Bez něj se vypíše počítadlo odkazovaného souboru či adresáře, s ním se vypíše počítadlo samotného symbolického odkazu.
2 Názvy vytvářených symbolických odkazů se odvodí od názvů v „cestě/k/cíli“.
3 Obsah odkazů musí mít délku 1 až 4095 bajtů, jinak však v tomto případě neprovádí příkaz „ln“ žádnou kontrolu smysluplnosti obsahu odkazu. Toto je tedy preferovaný způsob vytváření symbolických odkazů na dosud neexistující soubory a adresáře.
4 Relativní symbolický odkaz si při přesunutí zachová svůj obsah doslovně, de facto se tedy přesune se odpovídajícím způsobem i to, kam ukazuje. Pokud chcete, aby i po přesunutí odkazoval na původní cíl, budete ho muset „opravit“. Toto se netýká absolutních symbolických odkazů.
5 Pozor! Pokud nemáte přístup do adresáře, kam symbolický odkaz vede, bude se vám vždy jevit jako neplatný! V případě pochybností raději hledejte neplatné odkazy s použitím „sudo“ nebo obsah vyhledaných odkazů kontrolujte.
Líbí se vám tento projekt a chcete, aby byl ještě lepší? Můžete mi s tím pomoci. Zmiňte se o něm technicky zdatným přátelům, opravte překlepy a nahlašte nefunkční zaklínadla, aby mohla být opravena; poskytněte mi zpětnou vazbu nebo se zapojte do vývoje nových kapitol. Další informace na GitHubu v dokumentu Jak se zapojit.
[BY-SA]

Veškerý obsah této stránky (text, obrázky, zdrojový kód) je možno upravovat a šířit pod podmínkami licence Creative Commons Attribution-ShareAlike 4.0 International. Upozorňuji, že uvedená licence vyžaduje uvedení seznamu autorů, licence a zdroje a poskytnutí stejné či kompatibilní licence k provedeným změnám, jsou-li nějaké. Příslušné údaje jsou dostupné na stránce „Přehled autorů“. Šíření obsahu bez těchto údajů nebo šíření upravené verze bez poskytnutí adekvátní licence k provedeným úpravám je pravděpodobně porušení licenčních podmínek a může být postihováno. Poskytování zdrojového kódu při šíření není touto licencí vyžadováno.

Pro nové verze, další informace, aktuální zdrojový kód a možnost se zapojit do projektu „Linux: Kniha kouzel“ navštivte jeho repozitář na GitHubu.