如果没有给出路径,为什么find会打印一个前导“ ./”?


13

如果没有给出路径,为什么会find打印出导致./结果的线索?

$ find
./file1
./file2
./file3

不打印出来的原因是什么?

$ find
file1
file2
file3

Answers:


16

原因,为什么你看到的,这是因为GNU的开发人员选择,以提供一个“合理”的行为时,没有给出路径。相反,POSIX并未声明该参数是可选的:find find

find实用程序将递归方式降低目录层次结构从由路径指定的每个文件,评估在遇到的每个文件中的操作数部分中描述的原色的构成的布尔表达式。每个路径操作数应按提供时的原样进行评估,包括所有尾随<slash>字符;层次结构中遇到的其他文件的所有路径名均应由当前路径操作数的串联组成(<slash>如果当前路径操作数未以1结尾)和相对于路径操作数的文件名。相对部分应不包含点或点点组件,不包含尾随字符,并且<slash>路径名组件之间只有一个字符。

您可以在每个摘要中看到不同之处。 GNU在约定中(按照惯例)可选项目:

find [-H] [-L] [-P] [-D debugopts] [-Olevel] [starting-point...]
       [expression]

而POSIX并不表示它可以是可选的:

find [-H|-L] path... [operand_expression...]

在GNU程序中,这是通过以下方式完成的ftsfind.c

  如果(空)
    {
      / *
       *我们在这里使用一个临时变量,因为某些操作会被修改
       *临时路径。因此,如果我们使用字符串常量,
       *我们有一个核心转储。最好的例子是,如果我们说
       *“ find -printf%H”(注意,不是“ find。-printf%H”)。
       * /
      char defaultpath [2] =“。”;
      返回查找(默认路径);
    }

"."为简化起见,使用了文字。这样您将看到相同的结果

find

find .

因为(并且POSIX同意),给定的路径将被用作结果的前缀(请参见上文的并置)。

只需做一些工作,就可以确定何时首次添加功能。它出现在1996年“ findutils”最初创建中(请参阅参考资料find.c):

+  /* If no paths are given, default to ".".  */
+  for (i = 1; i < argc && strchr ("-!(),", argv[i][0]) == NULL; i++)
+    process_top_path (argv[i]);
+  if (i == 1)
+    process_top_path (".");
+
+  exit (exit_status);
+}

从find 3.8的变更日志中,这显然是

Sat Dec 15 19:01:12 1990  David J. MacKenzie  (djm at egypt)

        * find.c (main), util.c (usage): Make directory args optional,
        defaulting to "."

11

通常,对文件进行后处理,在这种情况下,以开头文件名会具有巨大的优势./。特别是,如果文件名以开头-,则后续命令可以将该文件名解释为选项。 ./避免这种情况。

例如,考虑包含以下文件的目录:

$ ls
--link  --no-clobber

现在,想象一下如果没有./前面提供文件名,此命令将如何工作:

$ find -type f -exec cp -t ../ {} +

我们可以说明问题find本身。让我们在与上面相同的目录中运行它。以下作品:

$ find ./*
./--link
./--no-clobber

以下失败:

$ find *
find: unknown predicate `--link'
Try 'find --help' for more information.

1
这说得通。但是还有一个问题,为什么它不加“。”。当你跑步的时候find *
NR

@nr好点。我希望它具有某种历史兼容性。我在答案中添加了一个为什么这是不良行为的示例。
John1024 '16

3
有些版本file 要求用户提供路径(例如OS X上的BSD查找)。因此,您通常需要明确地说出类似的内容find . -type f ...。从那里开始,对于某些版本的find(例如GNU find)而言,默认设置为默认设置.并保留所有其他内容并不重要。
ilkkachu

1
find *不显示的原因.是因为*列出了所有文件和文件夹,但不包括.echo *在仅包含一个或两个文件的目录中执行操作,您将看到 .未列出该目录。这样,find *对每个扩展的文件进行操作。就像您find Desktop/在主目录中说的一样。您会看到输出为Desktop/foo_bar.txt
Sergiy Kolodyazhnyy

1
@ John1024:我相信MrigeshThomas Dickey正确回答了这个问题。这个答案说明了为什么以它的find行为方式来方便。您是否有任何权威参考信息来支持出于这种原因find而设计为以这种方式表现的隐含主张
G-Man说'恢复莫妮卡'

4

find命令需要搜索路径。如果我们未指定任何内容,它将使用当前目录(.)作为起点。同样,如果您通过路径,例如/tmp,它会将其视为起点。因此,结果。

如果当前目录:

        $ find
or
        $ find .

output:
        ./file1
        ./file2
        ./file3

如果/tmp目录:

        $ find /tmp

output:
        /tmp/file4
        /tmp/file5

如果abc目录在当前目录下:

        $ find abc

output:
        abc/file6
        abc/file7

如果当前目录下有多个目录:

        $ find fu bar

output:
        fu/file10
        fu/file11
        bar/file8
        bar/file9

是的,我同意find需要一个路径来搜索任何内容,并且该路径默认为当前目录。问题是,为什么它打印出的领先./的时候file.txt是一样的作为./file.txt
NR

1
它不是找到添加“。” 实际上,它在开始时会添加您提供的任何路径,无论是“ / tmp”,“ abc”还是“。”。它将分别返回所有值。
Mrigesh Priyadarshi

-2

如果未指定路径,则find命令将假定${PWD}为路径,并将其输出到其输出中。用户未指定路径不会更改find工作方式。默认情况下,find始终适用于路径。


1
我知道了。但是,如果你在执行它/tmp,那么$PWD/tmp不是./
nr

如果您想看前面的内容/tmp,请运行命令。find /tmp如果您未指定路径,则它将始终是当前目录,即./
MelBurslan

1
我并不是想看到前面的故事/tmp。那是不可能的$PWD
NR

我的道歉${PWD}是不正确的空话
MelBurslan

2
不,它不假定$ PWD。比较器的输出find .find $PWD并且find(没有路径,如果您发现支持的话)。
ilkkachu
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.