link simbólico para um diretório e caminho relativo

link simbólico para um diretório e caminho relativo

Criei um link simbólico com caminho absoluto para o diretório (Blink) e tenho, por exemplo, a seguinte árvore:

$ 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

então eu vou para /tmp/A e mudo o diretório para Blink:

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

cd ..me retorna para, /tmp/A mas se eu digitar, por exemplo, ls ../foorecebo um erro:

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

O comando cd interno resolve o caminho conforme necessário, mas ls externos consideram o .. como nível superior de /tmp/B e, portanto, não conseguem encontrar foo.

Qual é o problema aqui? Posso obter o arquivo foo de /tmp/A/Blink por caminho relativo como ../foo?

Responder1

O shell armazena o diretório de trabalho atual em $PWD. Isso é o que é usado para os componentes internos do shell cde pwd, e trata os links simbólicos como diretórios normais, como você viu. Às vezes isso é útil, às vezes não.

Você pode encontrar o diretório real usando pwd(digite help pwdpara mais detalhes):

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

Da mesma forma, cdtem uma opção -P(de novo, help cdé seu amigo):

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

Finalmente, você pode desativar completamente o "recurso":

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

Responder2

Eu não acho que você pode fazer isso. Hoje em dia, os shells monitoram como chegaram onde estão, controlam o diretório de trabalho atual por nome, em vez de apenas confiar no sistema de arquivos e no sistema operacional para mantê-lo. Isso significa que o integrado cdpode "fazer backup" do link simbólico, em vez de apenas seguir as cadeias ".." diretamente.

Mas quando você executa ls ../foo, lsnão percebe que o shell chegou a um diretório seguindo links simbólicos. lsfará um stat()em "../foo". A parte ".." vem do diretório atual, que possui apenas uma única entrada ".." para seu pai. A coisa toda do link simbólico não muda a forma como os diretórios têm um único "." e uma única entrada "..". Links simbólicos permitem que o kernel insira uma camada extra de indireção nos caminhos dos arquivos. Quando você passa "../whatever" para open()ou stat(), o kernel apenas usa o diretório de trabalho atual do processo que faz a chamada para descobrir qual diretório único é nomeado por "..".

Responder3

Bruce e ams deram lindas respostas explicando o comportamento por trás. Mas para realmente fazer o que ls ../foovocê estava pedindo, você poderia escolher algo como

ls $(dirname $PWD)/foo

Responder4

Você não pode fazer isso, porque/tmp/A/Blink éna verdade /tmp/B. Então, ls ../A/foofunciona.

Em vez disso, você pode achar útil podercdpara oreal /tmp/Bdiretório, em vez do alias /tmp/A/Blink. Para fazer isso, você pode usar a seguinte função em vez de cd(que você pode colocar em seu .bashrc)

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

lcd, é claro, funciona para diretórios normais e com links simbólicos.
Nota: readlink -fatua no destino final do link (quando os links são encadeados).

informação relacionada