查找 txt 文件时,我运行以下命令:
find . -name "*.txt" -print
这为我提供了当前目录下所有文本文件的列表。
但是,find . -name *.txt -print
给我以下错误:
find: paths must precede expression: mein.txt
这是普遍预期的行为吗?引号有什么区别?
答案1
在未加引号的令牌中,将由您的 shell 执行扩展,而不是您正在运行的命令。
这意味着,当您输入 时find . -name "*.txt" -print
, find 会接收文字*.txt
作为其参数之一,并使用此模式作为其选项的参数-name
,该选项将与应用 之前找到的文件名称相匹配-print
。
另一方面,当您输入 时find . -name *.txt -print
,shell 会传递扩展版本的*.txt
来查找。可能有几种情况:
*.txt
当前目录中没有匹配的文件:find 接收一个文字*.txt
(假设默认 bash 设置);*.txt
当前目录下只有一个文件匹配;假设它是a.txt
: find 接收此文件名,并匹配a.txt
从当前目录开始的所有名为 find 的文件;当前目录中有几个文件匹配
*.txt
(这似乎是您的情况):-name
接收第一个文件作为其参数,其他文件是要查找的进一步路径参数,它抱怨没有在表达式之前给出所有路径。
这是预期的行为。
我们假设以下文件层次结构:
.
├── a.txt
├── b.txt
├── c.txt
└── foo
├── a.txt
├── b.txt
└── c.txt
find 在每种情况下接收的实际参数可以通过将 find 调用替换为 来观察printf '%s\n'
,这将在其自己的行上打印每个扩展参数:
$ printf '%s\n' . -name "*.txt" -print
.
-name
*.txt
-print
$ printf '%s\n' . -name *.txt -print
.
-name
a.txt
b.txt
c.txt
-print
如您所见,鉴于现有文件,您发布的第二个调用等效于find . -name a.txt b.txt c.txt -print
.
答案2
这是预期的行为 - 它被称为“shell globbing”。如果没有引号,*.txt
shell 将扩展 ,将与该表达式匹配的整个文件列表传递给find
命令。通过将其括在引号中,您可以告诉 shell 将文字字符串传递*.txt
给find
.您可以使用其他转义方法(例如find . -name \*.txt
或 )来实现相同的保护find . -name '*.txt'
。