Що таке ~ (tilde), коли використовується як префікс до контуру?


11

Редагувати: це дублікат /programming/998626/meaning-of-tilde-in-linux-bash-not-home-directory/ . У мене немає репутації закривати це питання як дублікат.

Я не маю на увазі, ~як у домашньому каталозі, а про це:

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

Однак якщо я спробую це з іншою точкою кріплення, наприклад:

$ 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

Як ~називається в цьому контексті? Як це працює?

Редагувати: Більше інформації на основі деяких коментарів нижче:

  1. Я можу засвідчити, що fooце не ім’я користувача в моїй системі.
  2. При спробі автозаповнення ls -lah ~не всі параметри відображаються. тобто я вмію cd ~qux, коли quxне з’являється в автозаповнення. Знову quxне є користувачем у моїй системі.
  3. Якщо це важливо /some/mount/point, це мережа.
  4. Всі подробиці пропонують деякий названий макетний шлях, функцію Z оболонки розширення імені шляху, але це працює і в bash, який, мабуть, не підтримує такі речі, як названі шляхи оболонки Z.

5
~foo- домашній каталог користувача foo. Якщо користувача не вказано, типовим користувачем є типовий користувач.
DopeGhoti

Але в цьому випадку /some/mount/pointточно не мій домашній каталог. cd ~веде мене на/Users/$username/$HOME
RD

1
zshЗдається, також використовується тильда для позначення названих каталогів.
DopeGhoti

Я підозрював це теж !! За винятком причин, ряд команд, які я розмістив вище, працює також у bash ( bash -c "ls ~foo/bar") - який не має назви каталогів. Крім того, навіть в межах zsh, якщо я перевіряю env, я не бачу створених жодних названих каталогів. Я перебуваю на Mac OS, і я вважаю, що це особливість, характерна для OS X.
RD

1
Ти лише сказав ~foo. Візьміть власне рядок (не приклад foo) і зробіть grep "actual username" /etc/passwd. ~textповинні працювати лише для можливих імен користувачів для входу відповідно до посібника з bash (не обов'язково означає, що він фактично здатний увійти; наприклад ~lp, для системних користувачів , наприклад). У всіх моїх тестах, ~stringвідповідність stringімені користувача.
Сергій Колодяжний

Відповіді:


14

Що таке ~ foo

Цитата з посібника з bash (з додаванням акценту):

Якщо слово починається з котируваного символу тильди (`~ '), всі символи, що передують першому косого косого рядка (або всі символи, якщо немає косого косого рядка), вважаються префіксом тильди. цитується префікс tilde, символи в префіксі tilde після тильди трактуються як можливе ім’я для входу.

~foo розширюється на fooдомашній каталог користувача точно так, як зазначено в /etc/passwd. Зауважте, що це може включати імена користувачів системи; це не обов'язково означає користувачів користувача або те, що вони можуть фактично увійти в систему локально (наприклад, вони можуть увійти через SSH-ключі).

Насправді, як зазначено в коментарях , bashбуде використовуватися getpwnamфункція. Ця функція сама визначається POSIX стандартом, отже , має існувати на більшості Unix-подібних системах, в тому числі MacOS X . Ця функція не обмежується /etc/passwdлише та здійснює пошук у інших базах даних, таких як LDAP та NIS. Конкретний витяг із bash вихідного коду , tilde.cфайлу, починаючи з рядка 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;

Практичний приклад

Нижче ви можете побачити тести із іменами користувачів системи в моїй системі. Зверніть увагу на відповідний passwdзапис та результат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

Навіть якщо, наприклад, _aptобліковий запис заблоковано, як це було запропоновано результатами, passwd -S aptвін все ще відображає як можливе ім’я для входу:

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

Зверніть увагу: це не особливість macOS, а швидше функція оболонки.


Я сумніваюся, що оболонка може розраховувати на те, щоб дізнатись про дату закінчення терміну дії облікового запису або якщо він заблокований чи що-небудь при розширенні тильди. Наприклад, в Linux дата закінчення терміну придатності зберігається /etc/shadowразом із іншою захищеною інформацією про автентифікацію, наприклад паролем. Посилання в passwdтому, що стосується того, щоб зробити пароль недійсним: це не завадило б автентифікацію іншими способами.
ilkkachu

@ilkkachu Так, ти маєш рацію. Я перевірив це, додаючи testuserта змінюючи дату закінчення терміну дії пароля. Ім'я користувача все ще з’являється під час заповнення вкладки. Я вилучив цю частину з відповіді
Сергій Колодяжний

1
Єдина проблема з цією відповіддю полягає в тому, що вона цитує bashдовідкову сторінку (і, здається, стару). ОП фактично використовує zsh(могло бути зрозуміліше), хоча в коментарях зазначається, що bashмає таку саму поведінку.
Кен Уейн ВандерЛінде

2
Ви можете використовувати getent passwd fooзамість того, grep foo /etc/passwordщоб слідувати тим самим механізмам пошуку, що і оболонка - можливо, включаючи послуги мережевого каталогу, які згадує @Abigail.
RJHunter

1
Відповідь прийнята за біт "таких як LDAP та NIS", який у моєму випадку виявився правильним!
РД

5

Підсумовуючи, чому ви щось бачите ~foo/bar, це тому, що у вас є користувач, названий fooв системі, з папкою, названою barв їх домашньому каталозі.

Дивіться це рішення в іншій спільноті, яка пояснює, чому (tilde) ~- це не просто "домашній каталог".

Якщо у вас є ім’я користувача binу вашій системі, ви можете перерахувати вміст домашнього каталогу bin за допомогою команди:

ls ~bin

Ще одне, що ви можете спробувати, - це скористатись заповненням вкладки після того, як ви вкажете наступне:

ls -lah ~ tab

щоб побачити список домашніх каталогів користувачів, який ~буде розширено, якщо ви продовжите. Приклад (усічений) результат завершення вкладкиls -lah ~ tab

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

1
+1 для заповнення вкладки. Це чітко розкриває всі імена користувачів, від яких bash може отримати якомога більше імен для входу /etc/passwd. Це відразу допомагає з’ясувати, що відбувається, якщо користувач звичайно знає імена користувачів, які вони мають у системі.
Сергій Колодяжний

2
Дякуємо за підказку щодо завершення баш - це призвело до цікавих результатів автозаповнення. Хоча я ~fooробив автозаповнення, я можу засвідчити, що fooце не користувач у моїй системі (і справді не існує в /etc/passwd). Крім того, всі папки / файли /some/mount/pointвідображаються в автозаповнення, що дуже цікаво.
РД
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.