Che cos'è una ~ (tilde) se usata come prefisso per un percorso?


11

Modifica: questo è un duplicato di /programming/998626/meaning-of-tilde-in-linux-bash-not-home-directory/ . Non ho la reputazione di chiudere questa domanda come duplicata.

Non mi riferisco a ~come nella directory home ma piuttosto a questo:

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

Tuttavia, se lo provo con un punto di montaggio diverso, ad esempio:

$ 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

Come si ~chiama in questo contesto? Come funziona?

Modifica: ulteriori informazioni basate su alcuni dei commenti seguenti:

  1. Posso attestare che foonon è un nome utente sul mio sistema.
  2. Quando si tenta di completare automaticamente ls -lah ~non vengono visualizzate tutte le opzioni. cioè sono in grado cd ~qux, quando quxnon viene visualizzato nel completamento automatico. Ancora quxuna volta non è un utente nel mio sistema.
  3. Se è importante /some/mount/pointè una condivisione di rete.
  4. Tutti i dettagli suggeriscono alcuni Path Muckery con nome, una caratteristica della shell Z di espansione del percorso, ma funziona anche in bash, che apparentemente non supporta cose come i percorsi con nome della shell Z.

5
~fooè la home directory dell'utente foo. Se l'utente non è specificato, l'utente corrente è l'impostazione predefinita.
DopeGhoti,

Ma in questo caso, /some/mount/pointsicuramente non è la mia directory home. cd ~mi porta a /Users/$username/- che partite$HOME
RD

1
zshsembra utilizzare anche la tilde per indicare le directory con nome.
DopeGhoti,

Lo sospettavo anch'io !! Tranne per qualche motivo la serie di comandi che ho postato sopra funziona anche in bash ( bash -c "ls ~foo/bar") - che non ha directory nominate. Inoltre anche all'interno di zsh, se ispeziono il file env, non vedo alcuna directory impostata. Sono su Mac OS e ritengo che questa sia una funzionalità specifica di OS X.
RD

1
Hai solo detto ~foo. Prendi la stringa attuale (non l'esempio foo) e fallo grep "actual username" /etc/passwd. ~textdovrebbe funzionare solo per i nomi utente di accesso possibili secondo il manuale bash (non significa necessariamente che sia effettivamente in grado di accedere; nel caso di utenti del sistema come ~lp, ad esempio). In tutti i miei test, ~stringcorrisponde a stringessere username.
Sergiy Kolodyazhnyy,

Risposte:


14

Cos'è ~ foo

Citazione dal manuale di bash (con enfasi aggiunta):

Se una parola inizia con un carattere tilde non quotato (`~ '), tutti i caratteri che precedono la prima barra non quotata (o tutti i caratteri, se non è presente una barra non quotata) sono considerati un prefisso tilde. Se nessuno dei caratteri nella vengono citati il ​​prefisso tilde, i caratteri nel prefisso tilde che segue la tilde vengono trattati come un possibile nome di accesso.

~foo si espande nella foohome directory dell'utente esattamente come specificato in /etc/passwd. Si noti che ciò può includere nomi utente di sistema; non significa necessariamente utenti umani o che possono effettivamente accedere localmente (ad esempio possono accedere tramite chiavi SSH).

Infatti, come notato nei commenti , bashutilizzerà la getpwnamfunzione. Tale funzione si è specificato da POSIX norma, quindi dovrebbe esistere più Unix sistemi, compresi MacOS X . Questa funzione non è limitata /etc/passwde cerca solo altri database, come LDAP e NIS. Estratto particolare dal bash codice sorgente , tilde.cfile, a partire dalla riga 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;

Esempio pratico

Di seguito puoi vedere i test con i nomi utente di sistema sul mio sistema. Prestare attenzione passwdall'immissione e al risultato corrispondenti dils ~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

Anche se ad esempio l' _aptaccount è bloccato come suggerito dall'output passwd -S apt, viene comunque visualizzato come nome di accesso possibile:

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

Nota: questa non è una funzionalità specifica di macOS, ma piuttosto una funzionalità specifica della shell.


Dubito che la shell possa fare affidamento sul scoprire qualcosa sulla data di scadenza dell'account o se è bloccata o qualcosa quando si espande la tilde. Ad esempio su Linux, la data di scadenza è memorizzata /etc/shadow, insieme alle altre informazioni di autenticazione protetta, come la password. Il riferimento passwdè solo per rendere la password non valida: ciò non impedirebbe l'autenticazione con altri mezzi.
ilkkachu,

@ilkkachu Sì, hai ragione. L'ho provato con l'aggiunta testusere la modifica della data di scadenza della password. Il nome utente appare ancora al completamento della scheda. Ho rimosso quel poco dalla risposta
Sergiy Kolodyazhnyy,

1
L'unico problema con questa risposta è che cita la bashpagina man (e quella vecchia a quanto pare). L'OP sta effettivamente usando zsh(avrebbe potuto essere più chiaro), anche se nei commenti si dice che bashha lo stesso comportamento.
Ken Wayne VanderLinde,

2
Puoi usare getent passwd fooinvece di grep foo /etc/passwordseguire gli stessi meccanismi di ricerca della shell, magari includendo i servizi di directory basati su rete citati da @Abigail.
RJHunter,

1
Accettato come risposta per il bit "come LDAP e NIS", che è risultato corretto nel mio caso!
RD

5

In sintesi del motivo per cui stai vedendo qualcosa ~foo/bar, è perché hai un utente nominato foosul sistema con una cartella nominata barnella loro directory home.

Vedi questa soluzione in un'altra comunità che spiega perché (tilde) ~è più di una semplice "directory home".

Se hai un utente chiamato binsul tuo sistema, puoi elencare il contenuto della home directory di bin con il comando:

ls ~bin

Un'altra cosa che puoi provare è utilizzare il completamento della scheda dopo aver digitato quanto segue al prompt (non tornare a capo, usa semplicemente il tasto Tab):

ls -lah ~ tab

per visualizzare l'elenco delle home directory degli utenti che ~verranno espanse se si continua. Esempio di output (troncato) del completamento della scheda dils -lah ~ tab

$ ls -lah ~ [tab]
~antman/            ~games/
~bin/               ~mail/

1
+1 per il completamento della scheda. Questo rivela chiaramente tutti i nomi utente che bash può ottenere come nomi di accesso possibili /etc/passwd. Aiuta immediatamente a chiarire cosa sta succedendo se l'utente ovviamente è a conoscenza dei nomi utente che ha sul sistema.
Sergiy Kolodyazhnyy,

2
Grazie per il suggerimento sul completamento bash - ha portato ad alcuni interessanti risultati di completamento automatico. Durante il ~foocompletamento automatico, posso attestare che foonon è un utente sul mio sistema (e in effetti non esiste in /etc/passwd). Inoltre, tutte le cartelle / i file vengono /some/mount/pointvisualizzati nel completamento automatico, il che è super interessante.
RD
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.