从找到手册页:
If --regex is not specified, PATTERNs can contain globbing characters. If any PATTERN contains no globbing characters, locate behaves as if the pattern were *PATTERN*.
现在,查看这些命令的输出:
test@ubuntu:~$ ls
Desktop Documents Downloads Firefox_wallpaper.png Music Pictures Public Templates Videos
test@ubuntu:~$
test@ubuntu:~$
test@ubuntu:~$ locate '/bin/bash*'
test@ubuntu:~$
test@ubuntu:~$
test@ubuntu:~$ locate /bin/bash*
/snap/core18/1880/bin/bash
/snap/core18/1880/usr/bin/bashbug
/snap/core18/1944/bin/bash
/snap/core18/1944/usr/bin/bashbug
/usr/bin/bash
/usr/bin/bashbug
如果您看到我的当前工作目录中没有完整路径名以 开头的文件/目录/bin/bash
。因此,我们不应该收到来自 的任何输出locate /bin/bash*
。为什么?根据shell 的全局特性,因为我的当前工作目录中没有这样的文件/目录,因此,*
将不会按原样展开和传递。因此,它应该等同于使用locate '/bin/bash*'
(这是我们上面运行的第二条命令)。由于这不会收到任何输出,因此这locate /bin/bash*
不应该也给出输出?
答案1
如果您看到我当前的工作目录中没有完整路径名以 /bin/bash 开头的文件/目录。因此,我们不应该收到来自locate /bin/bash*的任何输出
不,这不是 shell 通配符的工作方式 -/bin/bash*
匹配包括路径,因此只要找到匹配项(即/bin/bash
),它就会接收该参数。您可以通过运行设置了 shell 的调试参数locate
的命令来验证这一点:-x
$ set -x
$
$ locate /bin/bash*
+ locate /bin/bash
/bin/bash
/snap/core/10577/bin/bash
/snap/core/10577/usr/bin/bashbug
/snap/core/10583/bin/bash
/snap/core/10583/usr/bin/bashbug
/snap/core18/1932/bin/bash
/snap/core18/1932/usr/bin/bashbug
/snap/core18/1944/bin/bash
/snap/core18/1944/usr/bin/bashbug
/usr/bin/bashbug
由于(扩展的)模式不包含通配符,因此它相当于*/bin/bash*
。
更有趣的问题是,/bin/bash
既然贝壳显然可以定位自己,为什么它却不能定位自己呢?思考这是因为在较新版本的 Ubuntu 上/bin
是符号链接- 并且不记录符号链接。/usr/bin
updatedb
答案2
首先
该locate
命令将提供的模式与其数据库进行匹配。这就是它的工作原理。这意味着两件事:
无论你试图查找什么,它都必须存在于其数据库中,而仅仅存在于你的文件系统中是不够的。数据库应该定期更新,但有时需要时间,手动执行此操作的命令是
sudo updatedb
考虑到上述
locate
工作原理,从哪个目录运行命令没有任何区别,locate
因为locate
它本身不会搜索甚至不会查看当前目录。它所知道的只是它的数据库。
第二
当你传递不受保护(未引用)的模式时包含通配符要定位的字符,模式不会传递给locate
。在这种情况下传递给 的locate
是 shell 本身完成的扩展版本,其中可能包含各种内容,之后会被 shell 视为多个模式,locate
它会将所有这些内容与其数据库进行比较并相应地打印输出。在这种情况下,您没有可靠的方法来控制传递给 的内容locate
,这取决于 shell 的决定。
防止 shell 干扰和扩展包含通配符的模式的正确方法是保护或转义这些字符。简而言之使用引号围绕图案单圈或双圈,如下所示:
locate '/bin/bash*'