仅列出不包含文件的最浅目录,一直向下

仅列出不包含文件的最浅目录,一直向下

假设这个文件系统结构:

ROOT
    DIR1A
        FILE
        DIR2A
        DIR2B
            DIR3A
    DIR1B
        DIR2C
        DIR2D
            DIR3B
    DIR1C
        DIR2E
            FILE

从任意目录开始,我如何才能仅列出其最浅的子目录,而这些子目录又包含a)什么都没有或b)一直向下仅包含空目录,但不列出所述空子目录?

也就是说,在上面的情况下,如果我从 ROOT 开始:

  1. DIR1A 不会列出,因为它包含一个文件。
  2. DIR2A 将被列出,因为它不包含任何内容。
  3. DIR2B 将被列出,因为它只包含空目录。
  4. DIR3A 不会被列出,因为它位于已列出的较浅目录中。
  5. DIR1B 将被列出,因为它只包含空目录。
  6. DIR1B 的子目录不会被列出,因为它们位于已列出的较浅目录中。
  7. DIR1C 和 DIR2E 都不会列出,因为其中嵌套了一个文件。

我相信有一种更有效的方式来表达这一点。也许“我只想列出最高顺序的目录,其中不包含任何内容或仅包含空目录,一直向下”?

编辑:我试图澄清上面的一些语言。

答案1

为了避免遍历目录树太多次并最大限度地减少运行的命令数量,您可以这样做(假设 GNUfindsort类似awk的 GNU 支持 NUL 作为RecordS分隔符):

find . -type d -print0 -o -printf 'f/%h\0' |
  LC_ALL=C sort -zru |
  LC_ALL=C awk -F/ -vRS='\0' '
    function parent(path) {
      sub("/[^/]*$", "", path)
      return path
    }
    $1 == "f" {
      sep = path = ""
      for (i = 2; i <= NF; i++) {
        black[path = path sep $i]
        sep = FS
      }
      next
    }
    ! ($0 in black) && ($0 == "." || parent($0) in black)'

我们将所有下面包含非目录文件的目录涂成黑色,然后打印具有黑色父级(或特殊情况下没有父级.)的非黑色目录。

请注意,如果目标是删除这些目录,您可以这样做:

find . -depth -type d -empty -delete

-delete意味着-depth,但为了清楚起见,我仍然将其添加到此处(正如 GNUfind手册所建议的那样)。-delete无论如何,只会删除空目录,这样-empty我们就可以避免在无法删除非空目录时出现错误消息。通过深度优先,我们最终会删除不包含非d目录文件的整个结构,删除叶子所在的分支之前的叶子。

-delete和是来自 BSD 和GNU的-empty非标准扩展,但现在两者都相当常见。如果你没有它们,你总是可以将两者替换为(并且可能会用 丢弃错误消息,尽管你会错过-delete-emptyfindfind-exec rmdir {} +2> /dev/null全部find和)的错误消息rmdir

答案2

迟来的,给你:

find -type d -exec sh -c '[ -z "$(find "$@" -type f -print -quit)" ]' _ {} \; -print -prune

例子

# Setup your configuration
mkdir -p root/{dir1a/{dir2a,dir2b/dir3b},dir1b/{dir2c,dir2d/dir3b},dir1c/dir2e}
touch root/{dir1a,dir1c/dir2e}/file

# Run the finder
find root -type d -exec sh -c '[ -z "$(find "$@" -type f -print -quit)" ]' _ {} \; -print -prune

# Output
root/dir1b
root/dir1a/dir2b
root/dir1a/dir2a

解释

依次为每个目录调用子shell exec,从顶层开始向下(即宽度优先)。它从当前点开始搜索文件,true如果没有则返回。 mainfind从它的 中获取状态结果exec,如果成功则打印当前目录并停止搜索该子树的其余部分。

相关内容