用作路径前缀时,~(波形符)是什么?

用作路径前缀时,~(波形符)是什么?

编辑:这是重复的https://stackoverflow.com/questions/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 shell 的路径名扩展功能,但这也适用于 bash,但 bash 显然不支持 Z shell 的命名路径之类的功能。

答案1

什么是~foo

引用自bash手册(额外强调):

如果单词以不带引号的波形符 (`~') 开头,则第一个不带引号的斜杠之前的所有字符(或所有字符,如果没有不带引号的斜杠)都被视为波形符前缀。波浪线前缀被引用,波浪线前缀中跟在波浪线后面的字符被视为可能的登录名。

~foofoo完全按照 中指定的方式 扩展到用户的主目录/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 特定的功能,而是 shell 特定的功能。

答案2

总而言之,您看到 的内容的原因~foo/bar是,您foo在系统上有一个名为的用户,并且bar在其主目录中有一个名为的文件夹。

另一个社区中的这个解决方案这解释了为什么(波形符)~不仅仅是“主目录”。

如果您的系统上有一个指定的用户bin,那么您可以列出以下内容bin的主目录通过命令:

ls ~bin

您可以尝试的另一件事是在提示符下键入以下内容后使用制表符完成(不要回车,只需使用制表键):

ls -lah ~ tab

查看用户主目录的列表,~如果继续,该列表将展开。制表符补全的示例(截断)输出ls -lah ~ tab

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

相关内容