
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 ../foo
recebo 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 cd
e 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 pwd
para mais detalhes):
$ pwd
/tmp/A/Blink
$ pwd -L
/tmp/A/Blink
$ pwd -P
/tmp/B
Da mesma forma, cd
tem 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 cd
pode "fazer backup" do link simbólico, em vez de apenas seguir as cadeias ".." diretamente.
Mas quando você executa ls ../foo
, ls
não percebe que o shell chegou a um diretório seguindo links simbólicos. ls
fará 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 ../foo
você 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/foo
funciona.
Em vez disso, você pode achar útil podercdpara oreal /tmp/B
diretó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 -f
atua no destino final do link (quando os links são encadeados).