我了解到,当我使用命令时,双引号将除 $, `, \ 之外的所有内容视为字符。
但是,当使用类似命令时,find -type f -name "*.jpg"
*.jpg
它位于双引号内。那么,这意味着我们想将*
和.
视为一个角色。因此,该find
命令应该输出具有名称的常规文件*.jpg
,而不是实现路径名扩展。
如果我们想做路径名扩展,我想我必须输入命令find -type f -name *.jpg
(不带双引号)。
但是,结果是一样的。为什么在此命令中使用双引号?
答案1
通配符扩展的工作原理有一个微妙之处。更改为不包含 .jpg 文件的目录并输入
echo *.jpg
它会输出
*.jpg
特别是,字符串 *.jpg 保持不变。但是,如果您更改为包含 .jpg 文件的目录,例如假设我们有两个文件:image1.jpg 和 image2.jpg,则 echo *.jpg 命令将不会输出
image1.jpg image2.jpg
并且 *.jpg 被扩展。
如果您输入
find . -name *.jpg
并且当您键入此内容时所在目录中没有 .jpg 文件,则 find 将收到参数“.”、“-name”和“*.jpg”。但是,如果您在包含 .jpg 文件(例如 image1.jpg 和 image2.jpg)的目录中键入此命令,则 find 将收到参数“.”、“-name”、“image1.jpg”和“image2.jpg” “,所以实际上会运行命令
find . -name image1.jpg image2.jpg
并发现会抱怨。如果省略引号,真正令人困惑的是是否只有一个 .jpg 文件(例如 image1.jpg)。那么通配符扩展将导致
find . -name image1.jpg
find 命令将查找所有基名为 image1.jpg 的文件。
旁白:这确实导致了一个有用的 bash 习惯用法,用于查看是否有任何文件与给定模式匹配:
if [ "$(echo *.jpg)" = "*.jpg" ]; then
# *.jpg has no matches
else
# *.jpg has matches
fi
但请注意,如果当前目录中有名为“*.jpg”的文件,则此操作将不起作用。为了更加防水,你可以这样做
if [ "$(echo *.jpg)" = "*.jpg" ] && [ ! -e "*.jpg" ]; then
# *.jpg has no matches
else
# *.jpg has matches
fi
(虽然与问题没有直接相关,但我添加了这一点,因为它说明了通配符扩展如何工作的一些方面。)
答案2
您需要转义名称模式中的星号,因为find
想要在它搜索的所有各个目录中进行自己的全局扩展。如果不进行转义,则*
shell 会扩展 ,并且仅针对当前目录。这可能会产生非法find
调用。