创建一个Bash脚本来删除不包含特定文件类型的文件夹。

3

我最近遇到了一个问题。

我使用了一个工具将所有的音乐文件按照标签移动到相应的目录中。这样就留下了很多几乎空的文件夹。这些文件夹通常包含 thumbs.db 文件或某种形式的专辑封面图像。mp3 文件已经在它们的新目录中拥有了正确的专辑封面图像,因此旧目录可以删除。

基本上,我需要查找 D:/Music/ 中的任何不满足以下条件的目录:

-没有子目录

-不包含任何 mp3 文件

然后删除它们。

我认为这在 shell 脚本或 bash 脚本或其他 Linux/Unix 系统中比在 Windows 8.1 中更容易实现(哈哈)。

有什么建议吗?我对编写这样的脚本并不是很有经验。


1
我建议你在尝试这样的脚本时要非常小心。你可能需要在开始之前备份所有东西。 - Beta
@Beta 我计划使用find命令并将其保存到文本文件中,以便在删除任何内容之前查看脚本正在查找和删除的内容。不过还是谢谢你的建议,我的整个音乐目录已经备份好了,以防万一 :) - user2133809
Linux还是Windows?路径D:/Music/仅适用于Windows。 - BMW
@BMW Linux。抱歉,我主要使用Windows。我相信当驱动器在Ubuntu中被挂载时,Linux目录是/media/justin/"Local Disk"/Music - user2133809
3个回答

4

这应该让你开始了解

find /music -mindepth 1 -type d |
while read dt
do
  find "$dt" -mindepth 1    -type d | read && continue
  find "$dt" -iname '*.mp3' -type f | read && continue
  echo DELETE $dt
done

1

在这里找到了问题,类似于@user2133809,这些命令删除了必要的文件而不是必须删除的文件。 看起来可能会有一个find命令的差异,它可能并不总是成功地列出属性。但是使用sed查找必要的文件扩展名帮助我成功地形成了一个包含我想要保留的文件的目录列表。 将上面的解决方案与this solution结合起来,提供了一个清晰的管道来删除不需要的文件列表并安全地删除它们。 我的工作脚本更改了non-empty-dirs.tmp的创建方式,如下所示:

find . -type f -name '*.mp3*' | sed -r 's|/[^/]+$||' |sort |uniq > non-empty-dirs.tmp

我没有足够的声望@James,但感谢您分享这个简洁的答案。


0

这是一个简短的故事...

find . -name '*.mp3' -o -type d -printf '%h\n' | sort | uniq > non-empty-dirs.tmp
find . -type d -print | sort | uniq > all-dirs.tmp
comm -23 all-dirs.tmp non-empty-dirs.tmp > dirs-to-be-deleted.tmp

less dirs-to-be-deleted.tmp

cat dirs-to-be-deleted.tmp | xargs rm -rf

请注意,您可能需要运行所有命令几次(取决于您的存储库目录深度),然后才能完成删除所有递归空目录的操作...

长话短说...

您可以从两个基本角度来解决此问题:要么找到所有目录,然后迭代每个目录,检查它是否包含任何mp3文件或任何子目录,如果没有,则标记该目录以进行删除。这种方法可以奏效,但在非常大的存储库上,您可能会遇到显着的运行时间。

另一种方法,我认为更有趣的方法是构建一个不应被删除的目录列表,并将该列表从所有目录列表中减去。让我们逐步实现第二种策略...

首先,要找到包含mp3文件的所有目录的路径,您可以简单地执行以下操作:

find . -name '*.mp3' -printf '%h\n' | sort | uniq

这意味着“查找以 .mp3 结尾的任何文件,然后打印其父目录的路径”。

现在,我肯定可以命名至少十种不同的方法来查找包含至少一个子目录的目录,但是保持与上述相同的策略,我们可以轻松地得到...

find . -type d -printf '%h\n' | sort | uniq

这意味着:“查找任何目录,然后打印其父目录的路径。”
这两个查询可以在单个调用中组合,生成一个包含所有不应被删除的目录路径的列表。让我们将该列表重定向到一个临时文件中。
find . -name '*.mp3' -o -type d -printf '%h\n' | sort | uniq > non-empty-dirs.tmp

让我们同样生成一个文件,其中包含所有目录的路径,无论它们是否为空。

find . -type d -print | sort | uniq > all-dirs.tmp

所以,我们在一边有所有目录的完整列表,在另一边有不应该被删除的目录列表。现在怎么办?有很多策略,但这里有一个非常简单的:

comm -23 all-dirs.tmp non-empty-dirs.tmp > dirs-to-be-deleted.tmp

一旦你有了那个,审查一下,如果你满意的话,就通过xargs将其导入rm以实际删除目录。

cat dirs-to-be-deleted.tmp | xargs rm -rf

非常感谢。我正在学习计算机科学,因此这个解释对我很有帮助。我觉得我可能会想到这个逻辑,但是天哪,我不擅长脚本。谢谢! - user2133809
编辑:我运行了这个程序,虽然逻辑是正确的,但它找到要删除的目录非常不正确。 :/ - user2133809

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接