O que é um ~ (til) quando usado como um prefixo para um caminho?

11

Editar: esta é uma cópia de link . Eu não tenho a reputação de fechar essa questão como duplicata.

Não estou me referindo a ~ como no diretório inicial, mas sim:

$ ls ~foo/bar
/some/mount/point/foo/bar

No entanto, se eu tentar com um ponto de montagem diferente, por exemplo:

$ mount | ag "/dev "
devfs on /dev (devfs, local, nobrowse)
$ ls /dev/stdin
/dev/stdin
$ ls ~stdin
zsh: no such user or named directory: stdin . 
# bash has a similar error message: 
ls: ~stdin: No such file or directory

O que é o ~ chamado neste contexto? Como isso funciona?

Editar: Mais informações com base em alguns dos comentários abaixo:

  1. Posso atestar que foo não é um nome de usuário no meu sistema.
  2. Ao tentar preencher automaticamente ls -lah ~ nem todas as opções são mostradas. ou seja, posso cd ~qux , quando qux não aparece no preenchimento automático. Novamente qux não é um usuário no meu sistema.
  3. Se for importante, /some/mount/point é um compartilhamento de rede.
  4. Todos os detalhes sugerem alguns muckery de caminho nomeado, um recurso shell Z da expansão do nome do caminho, mas isso também funciona no bash, que aparentemente não suporta coisas como os caminhos nomeados do shell Z.
por R.D. 13.02.2018 / 21:28

2 respostas

14

O que é ~ foo

Citação do manual do bash (com adição de ênfase):

If a word begins with an unquoted tilde character ('~'), all of the characters preceding the first unquoted slash (or all characters, if there is no unquoted slash) are considered a tilde-prefix.If none of the characters in the tilde-prefix are quoted, the characters in the tilde-prefix following the tilde are treated as a possible login name.

~foo expande para o diretório base do usuário de foo exatamente conforme especificado em /etc/passwd . Observe que isso pode incluir nomes de usuários do sistema; isso não significa necessariamente usuários humanos ou que eles podem realmente efetuar login localmente (eles podem efetuar login via chaves SSH, por exemplo).

Na verdade, conforme observado no comentários , bash usará a função getpwnam . Essa função em si é especificada pelo padrão POSIX , portanto deve existir na maioria dos sistemas semelhantes ao Unix, incluindo macOS X . Essa função não está limitada a /etc/passwd apenas e pesquisa outros bancos de dados, como LDAP e NIS. Trecho particular de bash código-fonte , tilde.c arquivo, começando na linha 394:

  /* No preexpansion hook, or the preexpansion hook failed.  Look in the
     password database. */
  dirname = (char *)NULL;
#if defined (HAVE_GETPWNAM)
  user_entry = getpwnam (username);
#else
  user_entry = 0;

Exemplo prático

Abaixo você pode ver testes com nomes de usuários do sistema no meu sistema. Preste atenção na entrada passwd correspondente e no resultado de ls ~username

$ grep '_apt' /etc/passwd
_apt:x:104:65534::/nonexistent:/bin/false
$ ls ~_apt
ls: cannot access '/nonexistent': No such file or directory
$ grep '^lp' /etc/passwd
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
$ ls ~lp
ls: cannot access '/var/spool/lpd': No such file or directory

Mesmo se, por exemplo, a conta _apt estiver bloqueada, conforme sugerido pela saída de passwd -S apt , ela ainda será exibida como o nome de login possível:

_apt L 11/29/2017 0 99999 7 -1

Observe: Esse não é um recurso específico do MacOS, mas um recurso específico do shell.

    
por 13.02.2018 / 22:31
5

Em resumo de porque você está vendo algo para ~foo/bar , é porque você tem um usuário chamado foo no sistema com uma pasta chamada bar em seu diretório inicial.

Veja esta solução em outra comunidade que explica porque (til) ~ é mais do que apenas "diretório inicial".

Se você tem um usuário chamado bin em seu sistema, então você pode listar o conteúdo do diretório home bin pelo comando:

ls ~bin

Uma outra coisa que você pode tentar é usar a conclusão de tabulação depois de digitar o seguinte em um prompt (não retorno de carro, apenas use a tecla tab):

ls -lah ~ guia

para ver a lista de diretórios base dos usuários à qual ~ expandirá se você continuar. Exemplo de saída (truncada) da conclusão da tabulação de ls -lah ~ tab

$ ls -lah ~ [tab]
~antman/            ~games/
~bin/               ~mail/
    
por 13.02.2018 / 22:31