Diferença estranha entre pwd e / bin / pwd

13

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

Mas se eu executar /bin/pwd , ele imprime /home/sim (o diretório atual não mudou).

De onde vem essa diferença?

    
por user3581976 19.07.2014 / 18:46

2 respostas

16

Na maioria dos shells, incluindo o bash, pwd é um shell embutido:

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

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

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

Por padrão, /bin/pwd ignora links simbólicos e imprime o diretório atual.

Em 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 pwd incorporado inclui o symlink por padrão, exceto que a opção -P é usada ou o -o physical set builtin está ativado.

Em 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.
    
por 19.07.2014 / 18:51
5

É 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 estar no tópico como uma resposta a esta pergunta. Isso é o que o programa pwd e a função de biblioteca getcwd fazem. Nos primeiros dias do Unix, elas eram as únicas maneiras de descobrir qual era o seu diretório de trabalho. Aqui está a parte da resposta à sua pergunta que não consigo encontrar em qualquer das outras respostas, ou mesmo em qualquer outro lugar deste site (após 42 segundos de pesquisa):

  • Quando o shell é iniciado, ele recebe seu diretório de trabalho atual (provavelmente chamando getcwd ).
  • Depois disso, sempre que você fizer um cd , pushd ou popd , o shell mantém o controle do diretório de trabalho usando as funções de manipulação de string. Por exemplo,

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

    Ele faz isso para salvar o "custo" de chamar getcwd . Mas isso é um trade-off, pois pode resultar em informações incorretas.

  • O comando pwd (builtin) exibe simplesmente a noção lembrada / computada do shell do que é o diretório de trabalho.
  • Além disso, o shell coloca sua noção lembrada / computada do que o diretório de trabalho é na variável de ambiente PWD, para a conveniência de processos do usuário. Um processo nunca deve depender disso, se quiser informações precisas.

Então, a questã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 tem acesso à noção do shell sobre o diretório de trabalho, e assim determina o verdadeiro diretório de trabalho em si, da maneira antiga. (Exceção: o programa /bin/pwd pode examinar a variável de ambiente PWD, e aparentemente acontece quando você especifica -L .) Veja outro exemplo de como o shell pode ficar confuso:

cd /home/sim/aa # Assume that /home, /home/sim,  and /home/sim/aa
# are all real directories (not symbolic links).
pwd # Output: /home/sim/aa, which is correct.
mv ../aa ../bb
pwd # Output: /home/sim/aa, which is incorrect.
/bin/pwd # Output: /home/sim/bb, which is correct.

E, caso você não saiba, digite ln -s . aa e cd aa . seu diretório de trabalho atual não mudou , mais do que quando você digita cd . - porque, essencialmente, isso é o que você faz quando digita cd aa .

    
por 24.07.2014 / 02:16