collegamento simbolico a una directory e percorso relativo


15

Ho creato un collegamento simbolico con percorso assoluto alla directory (Blink) e ho ad esempio il seguente albero:

$ ls -l /tmp/A
total 0
lrwxrwxrwx 1 root root 6 Apr  3 12:27 Blink -> /tmp/B
-rw-r--r-- 1 root root 0 Apr  3 12:27 foo

$ ls -l /tmp/B
total 0
-rw-r--r-- 1 root root 0 Apr  3 12:27 bar

poi vado in / tmp / A e cambio directory in Blink:

$ cd /tmp/A
$ pwd
/tmp/A
$ cd Blink
$ pwd
/tmp/A/Blink

cd ..mi restituisce /tmp/A ma se scrivo per esempio ls ../fooavrò un errore:

ls: ../foo: No such file or directory

il comando cd incorporato risolve il percorso come necessario, ma ls esterno considera .. come livello superiore di / tmp / B e quindi non riesce a trovare foo.

Qual è il problema qui? Posso ottenere il file foo da / tmp / A / Blink per percorso relativo come ../foo?


La stessa domanda viene inviata su SuperUser
Peter.O il

Risposte:


13

Non penso che tu possa farlo. Al giorno d'oggi le conchiglie tengono traccia di come sono arrivate dove si trovano, tengono traccia dell'attuale directory di lavoro per nome, piuttosto che basarsi sul file system e sul sistema operativo per mantenerlo. Ciò significa che è integratocd può "eseguire il backup" del collegamento simbolico, anziché seguire direttamente le catene "..".

Ma quando si esegue ls ../foo, lsnon si rende conto che la shell è arrivata a una directory seguendo i collegamenti simbolici. lsfarà un stat()"../foo". La parte ".." proviene dalla directory corrente, che ha solo una voce ".." per il suo genitore. L'intera cosa simbolica del collegamento non cambia il modo in cui le directory hanno un singolo "." e una singola voce "..". I collegamenti simbolici consentono al kernel di inserire un ulteriore livello di indiretta nei percorsi dei file. Quando si passa "../whatever" a open()o stat(), il kernel utilizza solo la directory di lavoro corrente del processo che esegue la chiamata per capire quale singola directory è denominata da "..".


17

La shell memorizza la directory di lavoro corrente in $PWD. Questo è ciò che viene utilizzato per i builtin della shellcd e pwd, e si tratta di link simbolici come directory normali, come avete visto. A volte questo è utile, a volte no.

Puoi trovare la directory reale usando pwd(digita help pwdper maggiori dettagli):

$ pwd
/tmp/A/Blink
$ pwd -L
/tmp/A/Blink
$ pwd -P
/tmp/B

Allo stesso modo, cdha un'opzione -P(di nuovo, help cdè tuo amico):

$ cd /tmp/A/Blink
$ pwd
/tmp/A/Blink
$ cd -P ..
$ pwd -P
/tmp

Infine, puoi disattivare completamente la "funzione":

$ set -P
$ cd /tmp/A/Blink
$ pwd
/tmp/B

Grazie, sono a conoscenza della funzione set -P, ma ero confuso dal comportamento del comando ls ...
user478681

Come ho detto, l'uso set -Pe il comportamento iniziano a dare un senso. :)
AMS

2

Bruce e Ams hanno dato belle risposte spiegando il comportamento dietro. Ma per fare davvero quello ls ../fooche stavi chiedendo, potresti andare con qualcosa del genere

ls $(dirname $PWD)/foo

1

Non puoi farlo, perché in realtà lo /tmp/A/Blink è/tmp/B . Quindi ls ../A/foofunziona.

Potresti invece trovare utile essere in grado di eseguire il cd nella directory reale /tmp/B , anziché negli alias /tmp/A/Blink. Per fare ciò, puoi usare la seguente funzione invece di cd(che puoi mettere nel tuo .bashrc)

lcd() { cd $(readlink -f "$1"); }

lcd, ovviamente, lavora per le directory normali e simbolicamente collegate.
Nota: readlink -fagisce sul target finale del collegamento (quando i collegamenti sono concatenati).


1
cd -Psembra più semplice.
jw013,

@ jw013: hai ragione; è. Non ne ero a conoscenza .. grazie ..
Peter.O
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.