copia arquivos do local pai quando estou dentro de uma pasta simbolicamente vinculada

2

Suponha que eu tenha criado duas pastas em /tmp chamadas parent e child . child contém um arquivo chamado test-child.txt e parent contém um arquivo chamado test-parent.txt . Agora vamos dentro do parent e criar um link simbólico para o child . Em seguida, vá dentro do child e tente copiar o test-parent.txt do parent . A conclusão do bash funciona, mas a cópia real do arquivo falha -

cd /tmp
pwd
/tmp
mkdir parent
mkdir child
touch child/test-child.txt
ls child/
test-child.txt
cd parent
ln -sf ../child .
touch test-parent.txt
cd child
cp ../test-parent.txt .
cp: cannot stat ‘../test-parent.txt’: No such file or directory 

por que?

Além disso, quando eu estiver dentro de child e se eu disser -

pwd
/tmp/parent/child
    
por ramgorur 18.03.2015 / 02:53

2 respostas

2

Os shells rastreiam os links simbólicos como uma conveniência para os usuários. Isso tem o bom efeito de que cd foo && cd .. sempre retorna ao diretório original, mesmo quando foo é um link simbólico para um diretório. Tem dois tipos de desvantagens: a principal é que outros programas não se comportam dessa maneira; Além disso, o acompanhamento de diretórios simbólicos apresenta problemas próprios (o que acontece quando o link simbólico é alterado? o que acontece se o processo não tiver permissão para ler o link simbólico? etc.).

Os shells só podem fazer isso porque eles rastreiam todas as alterações no diretório, então eles se lembram de como você chegou lá. Quando um novo processo é iniciado, ele não recebe essa informação histórica. Sob o capô, ele descobre onde está, movendo-se para cima a partir do diretório atual, seguindo os links .. até atingir a raiz¹.

Se você chegou a um diretório através de links simbólicos, pode imprimir um caminho sem link simbólico com o pwd builtin, chamando pwd -P . Se você chamar outro programa do shell, não passe um caminho que contenha .. após os componentes do symlink, pois o programa o interpretaria de forma diferente. Em vez disso, elimine os componentes .. chamando pwd -P :

cp "$(cd .. && pwd -P && echo /)test-parent.txt" .

Se você quiser esquecer os links simbólicos usados nos comandos anteriores cd em uma sessão de shell, você pode executar

cd "$(pwd -P && echo /.)"

Isso muda para o que já é o diretório atual, portanto, não altera efetivamente o diretório atual do processo do shell, mas altera o caminho que o shell rastreou para o diretório atual, tornando-o sem link simbólico.

¹ É assim que a chamada getcwd opera tradicionalmente. Alguns kernels acompanham o diretório atual, mas não rastreiam links simbólicos, para compatibilidade com versões anteriores se não por outro motivo (mas também por causa dos casos sutis de bordas com links simbólicos).

    
por 19.03.2015 / 01:30
2

É porque cp não está jogando o mesmo jogo de link que seu shell é. Seu shell está rastreando os links para o diretório de trabalho atual como uma indirecção para o diretório de trabalho atual, mas o kernel não quer nenhuma dessas bobagens quando o shell chamar cp - em vez disso, o kernel fará o cp do diretório de trabalho atual de um caminho absoluto totalmente qualificado - e, portanto, seus links . e os links . do seu shell não são iguais . .

Você pode garantir um caminho absoluto para o diretório de trabalho atual tão facilmente quanto cd -P . e o mesmo funcionará para qualquer outro diretório como cd -P -- /any/other/directory . Você pode pelo menos usar pwd para imprimir o caminho absoluto para . como pwd -P , e em muitos shells ele alterará $PWD para o caminho absoluto também (em da mesma forma que cd -P . faz) .

Por exemplo:

cd /tmp
mkdir -p parent child
cd parent
ln -s ../child child
touch ./child/somefile
cd -L child                  ###the default
printf %s\n "$PWD"/*
cd -P .
printf %s\n "$PWD"/*

OUTPUT

/tmp/parent/child/somefile
/tmp/child/somefile
    
por 18.03.2015 / 03:16