我有一个目录层次结构。有些目录不包含文件,只包含其他目录。有些包含文件。
例如:
- movies
- 2022
- action
- movie.mp4
- another-movie.mp4
- 2023
- drama
- movie2.mp4
- 2024
- thriller
- movie3.mp4
- movie4.mp4
我想要一个find
可以提供此结果的命令:
/movies/2022/action
/movies/2023/drama
/movies/2024
/movies/2024/thriller
更新:目录中可以包含文件和目录。我更新了问题。例如,在2024
我有一个电影和另一个目录中。结果应包含/movies/2024
和/movies/2024/thriller
目录。
答案1
查找文件类型常规的并打印包含的目录。列表唯一以确保每个目录仅列出一次。如果在 GNU 系统上,即使存在包含换行符的文件路径,也可以可靠地完成此操作:
find /path -type f -print0 |
LC_ALL=C sed -z 's!/[^/]*$!!' |
LC_ALL=C sort -zu |
tr '\0' '\n'
标准地假设文件路径不包含换行符:
find /path -type f -print |
LC_ALL=C sed 's!/[^/]*$!!' |
LC_ALL=C sort -u
答案2
简单地,
find movies -type f -print | \
xargs -r dirname | \
sort --uniq
读man find xargs dirname sort
。
这是一个解释:
find
输出所有文件及其目录的列表,例如输出/movies/2022/action/movie.mp4 /movies/2022/action/another-movie.mp4 ...
到STDOUT
.xargs
打包尽可能多的文件名(请参阅 参考资料xargs --show-limits </dev/null
),并重复执行dirname
直到xargs
用完文件名。dirname
砍掉最右边的/
和文件名。例如/movies/2022/action/movie.mp4
成为/movies/2022/action
并且/movies/2022/action/another-movie.mp4
也成为/movies/2022/action/
sort --unique
消除重复的目录名称。
这种结构(find
、xargs
、 后处理)对于许多任务都很有用。花一些精力去理解它。
答案3
这应该可以做到:
find /movies -type d -not -empty -links 2
去引用这个答案:
链接数是文件的硬链接数。对于目录,硬链接的数量是(直接)子目录的数量加上父目录及其本身。
因此,当链接数为 2 时,只有父目录 ( ..
) 和自身 ( .
),因此没有子目录。
虽然这个答案适用于原始问题,但它不再适用于后来更新的问题。我仍然会留下它,因为它可能对其他人有帮助。
答案4
免责声明:我是 rawhide (rh) 的当前作者(请参阅 github.com/raforg/rawhide)。
使用 rawhide (rh),您可以执行以下操作:
rh /movies 'd && !empty && "[ -n \"$(rh -ref -- %S)\" ]".sh'
/movies
是一个搜索路径。
剩下的就是搜索条件:
d
意味着它是一个目录。
!empty
意味着它不为空。这不是必需的,但它可以通过减少下一位创建的 shell 进程的数量来加快速度。
"[ -n \"$(rh -ref -- %S)\" ]".sh
运行 shell 命令[ -n "$(rh -ref -- %S)" ]
,检查候选目录中是否有任何常规文件(嵌套使用rh
)。
rh -ref -- %S
是 的缩写rh -r -e f -- %S
。
就像-r
find 一样,-mindepth 1 -maxdepth 1
只能向下搜索一层。
指定与常规文件匹配的-e f
搜索条件表达式。f
停止--
命令行选项解析,以防止任何恶意文件名被解释为rh
(例如-xreboot
)的选项(感谢 Stéphane)。
是嵌套需要搜索%S
的当前候选目录的名称。rh
测试[ -n ... ]
嵌套rh
命令产生一些输出(即,它在候选目录中找到一些常规文件)。