有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 的目录(即不包含任何非目录)。
不过,对于递归find
s 来说,这相当慢。更好的解决方案可能涉及缓存找到文件的目录,或者从空目录开始一直工作到包含文件的分支的方法。