递归列出包含一个或多个 jpg 图像文件的所有目录

Mid*_*hed 5 shell find files

我正在尝试整理我的照片,这些照片由于各种历史原因而分散在我的系统中。为了让我能够开始这项任务,我一直在尝试使用命令行来构建包含一个或多个 jpg 文件的所有目录的列表。我确定我不必担心寻找其他图像文件格式,但我必须允许 jpg 以大写和小写形式出现。

我希望每个目录名称在最终列表中只出现一次。举个例子,如果我有以下目录,每个目录都包含一个或多个 jpg 或 JPG 文件......

~Mike/Pictures
~Mike/Pictures/London/Olympics
~Mike/Pictures/London
~Mike/Pictures/London/Holiday
~Mike/Photos
~Mike/Family History/Swaine
Run Code Online (Sandbox Code Playgroud)

我希望结果与每个目录只列出一次 - 无论它可能包含的图像文件数量如何 - 最好先排序然后写入文件

~Mike/Family History/Swaine
~Mike/Photos
~Mike/Pictures
~Mike/Pictures/London
~Mike/Pictures/London/Holiday
~Mike/Pictures/London/Olympics
Run Code Online (Sandbox Code Playgroud)

我的命令行技能还达不到这个要求!我可以使用许多简单形式的单个命令,但是一旦它们变得复杂和/或必须通过管道传输,事情往往会出错。

Kus*_*nda 7

假设 JPEG 图像文件具有后缀.jpg

find "$HOME" -type f -name '*.jpg' \
    -exec sh -c 'for d; do dirname "$d"; done' sh {} + | sort -u -o jpeg_dirs.txt
Run Code Online (Sandbox Code Playgroud)

这取决于您的名称中没有带有换行符的时髦目录名称。

使用 GNU find

find "$HOME" -type f -name '*.jpg' -printf '%h\n' | sort -u -o jpeg_dirs.txt
Run Code Online (Sandbox Code Playgroud)

这些find命令将在您的主目录下查找所有 JPEG 图像并打印找到它们的目录的名称。在sort -u将目录名称的列表,排序,并删除重复。结果将写入jpeg_dirs.txt当前目录中的文件。


在 2021 年初(3.3 年后)回顾这一点,我有点畏缩,因为我上面的解决方案虽然本身没有错,但有点倒退。它还对“漂亮的文件名”(没有换行符)做出了明显的假设。

当您使用find搜索目录时,不要像我上面那样搜索常规文件;实际上搜索目录。一旦我们有了目录,我们就可以查看它们中的每一个,看看它是否是一个文件匹配*.jpg*.JPG(其他文件名后缀很容易添加):

find "$HOME" -type f -name '*.jpg' \
    -exec sh -c 'for d; do dirname "$d"; done' sh {} + | sort -u -o jpeg_dirs.txt
Run Code Online (Sandbox Code Playgroud)

这会从您的主目录向下查看每个目录,并尝试扩展每个目录中的通配模式*.@(jpg|JPG)。这个模式,也可以写成两个独立的模式,*.jpgand*.JPG匹配我们正在寻找的所有文件。如果一个名称匹配,我们假设这是一个我们想要输出名称的目录。这将对仅包含具有这些后缀的子目录的目录产生误报。

我们运行内部bash脚本的 shell 选项允许我们匹配隐藏名称 ( dotglob),如果它不匹配任何内容,则允许 globbing 模式完全消失而不是保持未扩展 ( nullglob),并允许我们使用ksh-inspired 扩展通配模式@(...|...)

使用zsh外壳:

find "$HOME" -type f -name '*.jpg' -printf '%h\n' | sort -u -o jpeg_dirs.txt
Run Code Online (Sandbox Code Playgroud)

这将创建一个数组变量 ,list该变量具有仅存储唯一元素的属性。它被初始化为扩展文件名通配模式的结果。该模式匹配主目录中或以下的所有 JPEG 图像文件,:h最后从生成的路径名中删除实​​际文件名。在.使图案只匹配常规文件,并且DN行为像dotglobnullglobbash

  • @Nick 使用 `\( -iname '*.jpg' -o -iname '*.jpeg' \)` 来匹配多个后缀。 (2认同)