【问题标题】:GNU find: Search in current directory firstGNU find:首先在当前目录中搜索
【发布时间】:2011-05-12 00:41:07
【问题描述】:

如何让 find 先在当前文件夹中查找,然后在子文件夹中继续搜索?我有以下内容:

$ find . -iname '.note'
folder/1/.note
folder/2/.note
folder/3/.note
folder/.note

我想要的是这个:

$ find . -iname '.note'
folder/.note
folder/1/.note
folder/2/.note
folder/3/.note

有什么想法吗?

【问题讨论】:

  • 有趣。 Linux 上的 GNU find 给了我你的第一个输出,Cygwin 上的 GNU find 给了我你的第二个输出。不知道如何影响这一点; -depth 应该可以工作,但不能。
  • 这里的行为相同。 -depth 好像没有效果。
  • @DevSolar, @larsmans:有了这个输入,-depth 恰好产生了完全相同的结果。 -depth 对文件是在目录之前还是之后处理没有影响,它决定目录是在其内容之前还是之后处理。

标签: unix directory find depth directory-traversal


【解决方案1】:

find -s . -iname ".note" 没有帮助?或find . -iname '.note'|sort

【讨论】:

    【解决方案2】:

    解决方法是find . -iname '.note' | sort -r:

    $ find . -iname '.note' | sort -r
    folder/.note
    folder/3/.note
    folder/2/.note
    folder/1/.note
    

    但是在这里,输出只是以相反的顺序排序,不会改变 find 的行为。

    【讨论】:

    • 在 ASCII 排序中,. 位于 1 之前,因此您的输出取决于具有特定的整理语言环境 ($LC_COLLATE)。大多数整理语言环境实际上确实有这样的排序,但不是基本语言环境(C 或同义词POSIX)。此语言环境通常在脚本中使用,以避免某些应用程序无法处理与 ASCII 不兼容的排序。
    【解决方案3】:

    对于在 Linux 上使用 GNU find 的我来说,我得到了具有不同测试运行的两个订单。

    测试用例:

    rm -rf /tmp/depthtest ; mkdir -p /tmp/depthtest ; cd /tmp/depthtest ; for dir in 1 2 3 . ; do mkdir -p $dir ; touch $dir/.note ; done ; find . -iname '.note'
    

    通过这个测试,我得到了海报的第一个结果。注意1 2 3 . 的顺序。如果我将此顺序更改为 . 1 2 3

    rm -rf /tmp/depthtest ; mkdir -p /tmp/depthtest ; cd /tmp/depthtest ; for dir in . 1 2 3 ; do mkdir -p $dir ; touch $dir/.note ; done ; find . -iname '.note'
    

    我得到了海报的第二个结果。

    在任何一种情况下,将 -depth 添加到 find 都不起作用。

    编辑:

    我写了一个 perl oneliner 来进一步研究这个问题:

    perl -e 'opendir(DH,".") ; print join("\n", readdir(DH)),"\n" ; closedir(DH)'
    

    在运行测试用例 1 后,我针对 /tmp/depthtest 运行了这个,结果如下:

    .
    ..
    1
    2
    3
    .note
    

    我在测试用例 2 之后再次运行它,结果如下:

    .
    ..
    .note
    1
    2
    3
    

    确认结果按目录顺序排列。

    查找的-depth 选项仅控制是否./1/.note./1/之前或之后处理,而不是./.note或./1/在前,所以结果的顺序纯粹基于目录顺序(主要是创建顺序)。

    查看How do I recursively list all directories at a location, breadth-first? 以了解如何解决此问题可能会有所帮助。

    【讨论】:

      【解决方案4】:

      find的算法如下:

      • 对于命令行中给出的每个路径,让当前条目为该路径,然后:
        1. 将当前条目与表达式匹配。
        2. 如果当前条目是一个目录,则以未指定的顺序对该目录中的每个条目执行步骤 1 和 2。

      对于 -depth 主节点,步骤 1 和 2 以相反的顺序执行。

      您要求 find 做的是在第 2 步中考虑目录之前的文件。但 find 没有这样做的选项。

      在您的示例中,匹配文件的所有名称都位于同一目录中的子目录名称之前,因此 find . -iname '.note' | sort 可以工作。但这显然不能很好地概括。

      在目录之前处理非目录的一种方法是运行find 命令来迭代目录,并运行一个单独的命令(可能又是find)来打印该目录中的匹配文件。

      find -type d -exec print-matching-files-in {} \;
      

      如果你想使用find 表达式来匹配文件,这里是第二个find 命令的一般结构,它只迭代指定目录中的非目录,非递归(需要GNU 查找):

      find -type d -exec find {} -maxdepth 1 \! -type d … \;
      

      例如:

      find -type d -exec find {} -maxdepth 1 \! -type d -iname '.note' \;
      

      在zsh中可以写

      print -l **/(#i).note(Od)
      

      **/ 递归到子目录; (#i) (a globbing flag) 将以下内容解释为不区分大小写的模式,(Od) (a glob qualifier) 对递归遍历的结果进行排序,以便在子目录之前考虑目录中的文件。使用(Odon),输出在Od 规定的约束范围内按字典顺序排序(即主要排序标准在前)。

      【讨论】:

        【解决方案5】:

        在当前文件夹中查找

         find ./in_save/ -type f -maxdepth 1| more
        

        ==>73!

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-11-27
          • 1970-01-01
          • 2016-08-20
          • 2016-09-24
          • 1970-01-01
          • 2018-12-27
          • 1970-01-01
          • 2018-10-16
          相关资源
          最近更新 更多