cp SOMEFILE .. copia para um diretório diferente após o cd'ing através de um link simbólico

4

Considere a seguinte configuração:

~/Desktop/Public/subdir
~/Desktop/subdir --> ~/Desktop/Public/subdir (symbolic link)

Agora eu faço:

cd ~/Desktop/subdir

O que me leva ao diretório vinculado.

Se eu emitir agora o comando:

cd ..

Eu serei movido de volta para o diretório Desktop . Isso significa que o comando cd é sensível ao contexto - ele lembra que eu digitei subdir através do link simbólico.

No entanto, emitindo o comando

cp testfile ..

copia testfile para Desktop/Public .

Eu prefiro o comportamento de cd sobre o comportamento (geralmente imprevisível) de cp . De qualquer forma, pergunto-me qual é a razão para essa diferença de comportamento? Apenas uma coisa legada ou há uma boa razão?

    
por Konstantin Schubert 22.07.2013 / 15:24

3 respostas

3

O motivo pelo qual cd está ciente de que você digitou o diretório por meio de symlink é porque ele está integrado ao shell. O comando cp é um binário externo e é transmitido apenas por meio de argumentos de linha de comando e variáveis de ambiente. As variáveis de ambiente não contêm dados sobre como você entrou no diretório atual.

Se você estiver usando bash , poderá fazer com que cd funcione da mesma forma que cp se quiser que as coisas sejam consistentes. set -P fará isso. A partir do manpage:

          -P      If  set,  the shell does not follow symbolic links when executing commands such as cd that change the current working directory.  It uses the physical directory structure instead.  By default, bash follows the
                  logical chain of directories when performing commands which change the current directory.
    
por 22.07.2013 / 15:50
2

Quando cd funciona como descrito, só pode ser um truque de cd ou seu shell. .. é uma entrada para o diretório pai. No seu caso, o pai de subdir pode ser apenas Public e não Desktop . Assim, cp pensa corretamente e você terá o mesmo comportamento com redirecionamentos (como > ).

O exemplo de cd usa apenas algum truque "fácil de usar" para se comportar como faz. Consulte o link

Se você realmente precisa da funcionalidade, precisa usar algo como

cp testfile "${PWD##*/}"

(copie para o diretório pai do diretório atual, de acordo com o rastreamento de shell). Em zsh, você pode simplificar isso para cp testfile $PWD:h

    
por 22.07.2013 / 16:06
0

É exatamente o oposto: cp se comporta como qualquer outro aplicativo, ele interpreta .. como o diretório pai do diretório atual. Isso porque o kernel interpreta .. como o diretório pai do diretório atual.

Quando você executa cd por meio de um link simbólico, o caminho que você passa para cd não torna o diretório pai do diretório de destino aparente. Quando você executa cd ~/Desktop/subdir , o destino não é /home/konstantin/Desktop/subdir - esse é um link simbólico. O diretório de destino é /home/konstantin/Desktop/Public/subdir . (Ou, para ser pedante: o diretório de destino é um subdiretório chamado subdir de um subdiretório chamado Public of… de um subdiretório chamado home do diretório raiz.) /home/konstantin/Desktop/subdir/.. não é /home/konstantin/Desktop : a propriedade que o diretório pai de /…stuff…/subdir é /…stuff… só é válido na ausência de subdiretórios.

Como é conveniente pensar em links simbólicos para diretórios como se fossem diretórios, os shells executam o rastreamento de links simbólicos. Quando você executa cd , o shell lembra qual caminho (possivelmente usando links simbólicos) você usou para alcançar o destino. E quando você usa .. em um argumento para cd (ou builtins semelhantes de shell como pushd ), o shell executa uma interpretação textual de .. em vez de interpretá-lo como o diretório atual: cd /some/stuff/../more é transformado codificar%. Dessa forma, cd /some/more se comporta como se os links simbólicos fossem realmente diretórios.

A interpretação textual de cd é conhecida como rastreamento de diretório lógico, e a interpretação do sistema de arquivos de .. é conhecida como rastreamento de diretório físico. Se você quiser usar o rastreamento de diretório físico (por exemplo, para desativar a interpretação textual de .. ), passe a opção .. para -P . A opção cd força o rastreamento lógico, caso tenha sido desativado. O rastreamento lógico está desativado por padrão; você pode desativá-lo com -L no bash ou com set -P em zsh.

O comando setopt chase_links exibe o diretório atual conforme rastreado pelo shell. Como pwd , você pode passar a opção cd ou -L para forçar o rastreamento lógico ou físico.

Tudo isso está acontecendo dentro do shell. Aplicativos externos, como -P , não têm como saber qual rastreamento o shell está fazendo internamente. Portanto, se você quiser usar o rastreamento de diretório lógico em um argumento para um comando, precisará convertê-lo primeiro em um caminho que não dependa do rastreamento lógico.

A variável de shell cp mantém o controle do diretório atual ( PWD contém a mesma sequência que $PWD imprime). Se você quiser remover o último componente textual do caminho rastreado do diretório atual, em vez de anexar pwd , que só funciona com rastreamento lógico, você pode usar um método textual.

cp testfile "${PWD##*/}"

ou em zsh:

cp testfile $PWD:h

Se você quiser digitar /.. e não precisar pensar em expressar o diretório de maneira diferente, execute .. no diretório de destino desejado e use o caminho para o destino no argumento do comando.

cp testfile "$(cd .. && pwd)"
    
por 23.07.2013 / 03:55