如何找到包含一个或多个文件的所有目录?

如何找到包含一个或多个文件的所有目录?

我有一个目录层次结构。有些目录不包含文件,只包含其他目录。有些包含文件。

例如:

- 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

我读,但我无法弄清楚find命令。

更新:目录中可以包含文件和目录。我更新了问题。例如,在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消除重复的目录名称。

这种结构(findxargs、 后处理)对于许多任务都很有用。花一些精力去理解它。

答案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

就像-rfind 一样,-mindepth 1 -maxdepth 1只能向下搜索一层。

指定与常规文件匹配的-e f搜索条件表达式。f

停止--命令行选项解析,以防止任何恶意文件名被解释为rh(例如-xreboot)的选项(感谢 Stéphane)。

是嵌套需要搜索%S的当前候选目录的名称。rh

测试[ -n ... ]嵌套rh命令产生一些输出(即,它在候选目录中找到一些常规文件)。

相关内容