Diferença estranha entre pwd e / bin / pwd

15

Eu adicionei um link simbólico para o diretório atual com ln -s . aa. Se eu executar cd aa, e depois que eu executei pwd, a resposta será /home/sim/aa.

Mas se eu executar, /bin/pwdele será impresso /home/sim(o diretório atual não mudou).

De onde vem essa diferença?

user3581976
fonte

Respostas:

17

Na maioria dos shells, incluindo o bash, pwdexiste um shell:

$ type -a pwd
pwd is a shell builtin
pwd is /bin/pwd

Se você usar /bin/pwd, deverá usar a -Lopção para obter o mesmo resultado que o incorporado pwd:

$ ln -s . test
$ cd test && pwd
/home/cuonglm/test
$ /bin/pwd
/home/cuonglm
$ /bin/pwd -L
/home/cuonglm/test

Por padrão, /bin/pwdignora links simbólicos e imprime o diretório real.

De info pwd:

`-L'
`--logical'
     If the contents of the environment variable `PWD' provide an
     absolute name of the current directory with no `.' or `..'
     components, but possibly with symbolic links, then output those
     contents.  Otherwise, fall back to default `-P' handling.

`-P'
`--physical'
     Print a fully resolved name for the current directory.  That is,
     all components of the printed name will be actual directory
     names--none will be symbolic links.

O interno pwdinclui o link simbólico por padrão, exceto que a -Popção é usada ou o -o physicalconjunto interno está ativado.

De man bash:

pwd [-LP]
              Print the absolute pathname of the  current  working  directory.
              The pathname printed contains no symbolic links if the -P option
              is supplied or the -o physical option to the set builtin command
              is  enabled.  If the -L option is used, the pathname printed may
              contain symbolic links.  The return status is 0 unless an  error
              occurs  while  reading  the  name of the current directory or an
              invalid option is supplied.
cuonglm
fonte
Eu não tenho certeza de entender onde é que vêm de essas diferenças
user3581976
/bin/pwdignora o link simbólico por padrão, leia parte info pwdda minha resposta: imprima um nome totalmente resolvido para o diretório atual. Ou seja, todos os componentes do nome impresso serão nomes de diretório reais - nenhum será um link simbólico.
cuonglm
@ user3581976: Veja meu atualizado para mais claramente.
cuonglm
Por que existe um comando -L para pwd, embora ele esteja definido por padrão? E o shell não usa o comando / bin / pwd para executar o pwd?
user3581976
2
@ user3581976: Imagem com a qual você inicia seu shell set -o physical, agora pwdé -Popção de uso por padrão; se você não tem -Lopção, como imprimir o caminho que contém o link simbólico? Leia isto https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.htmlpara saber o que set -o physicalfaz.
cuonglm
7

É possível que um processo interrogue o sistema de arquivos para determinar seu diretório de trabalho atual, usando um método um pouco complicado demais para ser abordado no tópico como resposta a esta pergunta. É isso que o pwdprograma e a getcwdfunção da biblioteca fazem. Nos primeiros dias do Unix, elas eram as únicas maneiras de descobrir qual era seu diretório de trabalho. Aqui está a parte da resposta à sua pergunta que não consigo encontrar em nenhuma das outras respostas ou em qualquer outro lugar deste site (após 42 segundos de pesquisa):

  • Quando o shell é iniciado, ele obtém seu diretório de trabalho atual (provavelmente chamando getcwd).
  • Posteriormente, sempre que você fizer um cd,, pushdou popd, o shell acompanhará o diretório de trabalho usando funções de manipulação de string. Por exemplo,

    • Se seu diretório de trabalho é /home/sime você digita cd .., o shell calcula que é seu diretório de trabalho /home.
    • Se seu diretório de trabalho for /home/sime você digitar cd ., o shell calculará que seu diretório de trabalho ainda está /home/sim.
    • Se o seu diretório de trabalho é /home/sime você digita cd aa, o shell calcula esse diretório de trabalho /home/sim/aa- sem verificar se aaé um link simbólico.

    Isso é feito para economizar o "custo" da chamada getcwd. Mas isso é uma troca, pois pode resultar em informações incorretas.

  • O pwdcomando (builtin) simplesmente exibe a noção lembrada / calculada do shell sobre o que é o diretório de trabalho.
  • Além disso, o shell coloca sua noção lembrada / calculada do que o diretório ativo está na variável de ambiente PWD, para a conveniência dos processos do usuário. Um processo nunca deve contar com isso se desejar informações precisas.

Portanto, a conclusão é que o shell pode ficar confuso sobre onde está. Mas, se você digitar /bin/pwd, isso será executado em um processo separado, que não terá acesso à noção do shell sobre o que é o diretório de trabalho e, portanto, determinará o próprio diretório de trabalho, da maneira antiga. (Exceção: o /bin/pwdprograma pode examinar a variável de ambiente PWD, e aparentemente ocorre quando você especifica -L.) Aqui está outro exemplo de como o shell pode ficar confuso:

cd /home/sim/aa # Suponha que /home, /home/sim, e /home/sim/aa
# são todos os diretórios reais (não links simbólicos).
pwd # Saída:, /home/sim/aaque está correta.
mv ../aa ../bb
pwd # Saída: /home/sim/aaincorreta.
/bin/pwd # Saída:, /home/sim/bbque está correta.


E, caso você não tenha certeza disso, se você digitar ln -s . aae cd aa, em seguida, seu diretório de trabalho atual não mudou , mais do que quando você digita cd .- porque isso é essencialmente o que você está fazendo quando digita cd aa.

Scott
fonte
Obrigado, resposta muito boa, é isso que eu estava esperando;)
user3581976
2
Esta resposta parece um pouco inclinada . Há mais do -Lque economizar custos - e $PWDé uma variável de ambiente especificada pelo POSIX definida pelo usuário - os aplicativos de espaço do usuário provavelmente devem confiar nela (o que isso significa ...?) . De qualquer forma, embora eu não seja fã de links simbólicos, é prerrogativa do usuário indireto em tantas direções malucas quanto ele ou ela deve escolher com eles - e é isso que -Lé mais do que tudo.
mikeserv
1
Essa deve ser a resposta aceita (os links simbólicos não são o objetivo da pergunta).
Thomas Dickey