使用 "find … -delete" 仅从特殊子目录中删除图像文件
Using "find … -delete" to remove image files only from special subdirectories
我需要清理音乐 collection 中一些子目录中不需要的图像。我正在使用 Ubuntu 14.04 and/or Linux Mint 17.2 和使用 find 命令的 bash shell 脚本。
目录结构(最小示例)如下:
Tagged
Artist #1
Artist #1 - An Album
Artist #1 - A Track.flac
cover.jpg
something.png
Artist #1 - [compilations]
Artist #1 - A Track.flac
cover.jpg
something.png
Artist #2
Artist #2 - Another Album
Artist #2 - A Track.mp3
cover.jpg
只有在以“[compilations]”结尾的子文件夹中,我想删除所有jpeg and/or png图像(因为标记软件错误地把它们那里)。任何恰好位于普通 "album" 文件夹中的图像我也希望保留。
根据我的目录结构,名称中带有“[compilations]”的文件夹只能出现在 "Artist" 文件夹的正下方;所以最多两层深。
我想到了以下查找命令:
$ cd Tagged
$ find . -maxdepth 2 -type d -name '*\[compilations\]' -exec find {} -type f -iname '*.jp*g' -or -iname '*.png' -delete \;
这似乎需要一些时间,但文件 "./Artist #1/Artist #1 - [compilations]/cover.jpg" 和"./Artist #1/Artist #1 - [compilations]/something.png" 仍然存在(以及所有其他图像文件)。
作为 Linux 的新手,我假设我在使用 find 的 -delete 选项时犯了一个愚蠢的错误,因为以下命令(没有 -delete)正确显示文件:
$ find . -maxdepth 2 -type d -name '*\[compilations\]' -exec find {} -type f -iname '*.jp*g' -or -iname '*.png' \;
./Artist #1/Artist #1 - [compilations]/cover.jpg
./Artist #1/Artist #1 - [compilations]/something.png
所以这是我的问题:
- 为什么 -delete 不起作用?
- 对于 "extravaganza" 路径和文件名中的空格、全局字符和外来字符,此命令真的安全吗?
- 我如何重写上面的命令,仍然使用 bash 和 find?
- 是否可以优化命令(速度、安全、嵌套查找)?
在实际collection中,该命令必须遍历16899个文件夹,几乎所有文件夹都包含空格和外来字符(如捷克语、俄语、日语、希腊语、德语……),因此它必须是健壮的。
在此先感谢您的任何见解和启发!
经过一些实验,我认为我的错误是没有将 OR 部分 放在括号 中——似乎 find 使用了-delete 仅在最后一个 OR 的 右侧,即试图删除“*.png”。唉,我几乎所有的封面图片都是“*.jpg”,所以我认为它根本行不通!
所以我认为更正的命令应该是:
$ find . -depth -maxdepth 2 -type d -name '*\[compilations\]' -exec find {} -type f \( -iname '*.jp*g' -or -iname '*.png' \) -delete \;
它似乎在我上面的测试用例上工作正常。
尽管如此,一些确认会很好。也许是我其他问题的一些答案,仅供参考和学习。 谢谢!
您的 -delete
谓词仅适用于
-iname '*.png'
谓词,因为您错过了分组:当您给出 find
以下内容时:
-type f -iname '*.jp*g' -or -iname '*.png' -delete
由于布尔运算符的优先级,find
理解为:
\( -type f -iname '*.jp*g' \) -or \( -iname '*.png' -delete \)
要解决此问题,请使用:
-type f \( -iname '*.jp*g' -or -iname '*.png' \) -delete
我建议您将 -delete
替换为 -print
进行实验:您会看到 -delete
适用于什么!
现在,关于您的嵌套 find
:由于目录树的结构(您的文件仅在深度 3 中),您应该只能处理 find
的一个实例:
find -maxdepth 3 -path '*/*\[compilations\]/*' \( -iname '*.jp*g' -o -iname '*.png' \) -type f -print
(我用 -print
而不是 -delete
以便您可以在使用 -delete
执行命令之前检查命令)。
我需要清理音乐 collection 中一些子目录中不需要的图像。我正在使用 Ubuntu 14.04 and/or Linux Mint 17.2 和使用 find 命令的 bash shell 脚本。
目录结构(最小示例)如下:
Tagged
Artist #1
Artist #1 - An Album
Artist #1 - A Track.flac
cover.jpg
something.png
Artist #1 - [compilations]
Artist #1 - A Track.flac
cover.jpg
something.png
Artist #2
Artist #2 - Another Album
Artist #2 - A Track.mp3
cover.jpg
只有在以“[compilations]”结尾的子文件夹中,我想删除所有jpeg and/or png图像(因为标记软件错误地把它们那里)。任何恰好位于普通 "album" 文件夹中的图像我也希望保留。
根据我的目录结构,名称中带有“[compilations]”的文件夹只能出现在 "Artist" 文件夹的正下方;所以最多两层深。
我想到了以下查找命令:
$ cd Tagged
$ find . -maxdepth 2 -type d -name '*\[compilations\]' -exec find {} -type f -iname '*.jp*g' -or -iname '*.png' -delete \;
这似乎需要一些时间,但文件 "./Artist #1/Artist #1 - [compilations]/cover.jpg" 和"./Artist #1/Artist #1 - [compilations]/something.png" 仍然存在(以及所有其他图像文件)。
作为 Linux 的新手,我假设我在使用 find 的 -delete 选项时犯了一个愚蠢的错误,因为以下命令(没有 -delete)正确显示文件:
$ find . -maxdepth 2 -type d -name '*\[compilations\]' -exec find {} -type f -iname '*.jp*g' -or -iname '*.png' \;
./Artist #1/Artist #1 - [compilations]/cover.jpg
./Artist #1/Artist #1 - [compilations]/something.png
所以这是我的问题:
- 为什么 -delete 不起作用?
- 对于 "extravaganza" 路径和文件名中的空格、全局字符和外来字符,此命令真的安全吗?
- 我如何重写上面的命令,仍然使用 bash 和 find?
- 是否可以优化命令(速度、安全、嵌套查找)?
在实际collection中,该命令必须遍历16899个文件夹,几乎所有文件夹都包含空格和外来字符(如捷克语、俄语、日语、希腊语、德语……),因此它必须是健壮的。
在此先感谢您的任何见解和启发!
经过一些实验,我认为我的错误是没有将 OR 部分 放在括号 中——似乎 find 使用了-delete 仅在最后一个 OR 的 右侧,即试图删除“*.png”。唉,我几乎所有的封面图片都是“*.jpg”,所以我认为它根本行不通!
所以我认为更正的命令应该是:
$ find . -depth -maxdepth 2 -type d -name '*\[compilations\]' -exec find {} -type f \( -iname '*.jp*g' -or -iname '*.png' \) -delete \;
它似乎在我上面的测试用例上工作正常。
尽管如此,一些确认会很好。也许是我其他问题的一些答案,仅供参考和学习。 谢谢!
您的 -delete
谓词仅适用于
-iname '*.png'
谓词,因为您错过了分组:当您给出 find
以下内容时:
-type f -iname '*.jp*g' -or -iname '*.png' -delete
由于布尔运算符的优先级,find
理解为:
\( -type f -iname '*.jp*g' \) -or \( -iname '*.png' -delete \)
要解决此问题,请使用:
-type f \( -iname '*.jp*g' -or -iname '*.png' \) -delete
我建议您将 -delete
替换为 -print
进行实验:您会看到 -delete
适用于什么!
现在,关于您的嵌套 find
:由于目录树的结构(您的文件仅在深度 3 中),您应该只能处理 find
的一个实例:
find -maxdepth 3 -path '*/*\[compilations\]/*' \( -iname '*.jp*g' -o -iname '*.png' \) -type f -print
(我用 -print
而不是 -delete
以便您可以在使用 -delete
执行命令之前检查命令)。