递归查找空目录或其中没有文件的目录

递归查找空目录或其中没有文件的目录

find . -type d -empty命令,但只能找到字面上的空目录。

我想要实现的目标有点复杂:我想找到空目录或仅具有其他目录或空目录的目录,并且应该递归地传递此规则。

例如,在这个目录结构中: ~1/11/111/ 它将找到1/,1/11/1/11/111/ 但是,如果树中的任何一点都有一个文件,例如在这种情况下,如果其中有一个文件,1/11/111/file1则不应返回该文件之前的任何一个文件。因此,如果1/11/111/1111/旁边有一个空目录1/11/111/file1,则应返回 1111。

我想要这个的原因是因为我想删除我的空文件夹。

现在我可能可以通过find . -type d -empty -delete一遍又一遍地运行来做到这一点,但我想要一种在删除它们之前将其可视化的方法。

这可能吗?

答案1

要查看已删除的目录,只需插入-print

find . -type d -empty -print -delete

这将删除当前空目录下的任何子层次结构,同时显示已删除目录的路径名。

-delete操作意味着-depth,即遍历将从目录结构的底部开始并向上进行(深度优先遍历)。这意味着任何可能考虑删除的目录都已经处理了其子目录(如果它们为空,这些子目录将被删除)。

例子:

$ mkdir -p 1/2/3/4/5/6
$ tree
.
`-- 1
    `-- 2
        `-- 3
            `-- 4
                `-- 5
                    `-- 6

6 directories, 0 file
$ find . -type d -empty -print -delete
./1/2/3/4/5/6
./1/2/3/4/5
./1/2/3/4
./1/2/3
./1/2
./1
$ tree
.

0 directory, 0 file

如果一个目录有一个文件:

$ mkdir -p 1/2/3/4/5/6
$ touch 1/2/3/file
$ tree
.
`-- 1
    `-- 2
        `-- 3
            |-- 4
            |   `-- 5
            |       `-- 6
            `-- file

6 directories, 1 file
$ find . -type d -empty -print -delete
./1/2/3/4/5/6
./1/2/3/4/5
./1/2/3/4
$ tree
.
`-- 1
    `-- 2
        `-- 3
            `-- file

3 directories, 1 file

列出仅包含子目录但不删除它们的目录(使用bash):

shopt -s globstar
for dir in ./**/; do
    if [ -z "$(find "$dir" ! -type d -exec echo x \;)" ]; then
        printf '%s\n' "$dir"
    fi
done

这将循环遍历当前目录中的所有子目录(仅使用**shell glob),然后尝试查找其中任何一个都不是目录的内容。如果找到某些内容,则该目录不为空,否则输出空目录的路径名。

使用 GNU find,您可以添加-quit到上述命令的最末尾find(在 后面\;)以加快速度。

答案2

要打印空目录而不删除任何目录,我们要做的不仅仅是从叶子向上删除空目录。

像这样的事情可能会起作用:

find dir/ -type d ! -exec sh -c \
  'find "$1" ! -type d -print -quit | grep -q . >/dev/null' sh {} \; -print

外部find找到每个目录,并运行其他 find在他们每个人身上。内部find查看该目录(递归地)是否包含任何非目录,如果包含则返回真值。然后,外部find打印每个返回 false 的目录(即不包含任何非目录)。

不过,对于递归finds 来说,这相当慢。更好的解决方案可能涉及缓存找到文件的目录,或者从空目录开始一直工作到包含文件的分支的方法。

相关内容