定位命令和 shell 的通配符

定位命令和 shell 的通配符

找到手册页

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/binupdatedb

答案2

首先

locate命令将提供的模式与其数据库进行匹配。这就是它的工作原理。这意味着两件事:

  • 无论你试图查找什么,它都必须存在于其数据库中,而仅仅存在于你的文件系统中是不够的。数据库应该定期更新,但有时需要时间,手动执行此操作的命令是sudo updatedb

  • 考虑到上述locate工作原理,从哪个目录运行命令没有任何区别,locate因为locate它本身不会搜索甚至不会查看当前目录。它所知道的只是它的数据库。

第二

当你传递不受保护(未引用)的模式时包含通配符要定位的字符,模式不会传递给locate。在这种情况下传递给 的locate是 shell 本身完成的扩展版本,其中可能包含各种内容,之后会被 shell 视为多个模式,locate它会将所有这些内容与其数据库进行比较并相应地打印输出。在这种情况下,您没有可靠的方法来控制传递给 的内容locate,这取决于 shell 的决定。

防止 shell 干扰和扩展包含通配符的模式的正确方法是保护或转义这些字符。简而言之使用引号围绕图案单圈或双圈,如下所示:

locate '/bin/bash*'

相关内容