我想要一个聪明的算法来索引文件目录...指针?

lol*_*ter 10 python mysql sql database hash

我在Ubuntu(.mp3,.wav等)文件上有一个音乐目录.该目录可以包含所需数量的子目录,没有限制.我希望能够创建一个音乐库 - 也就是说,根据以下过滤器返回歌曲列表:

1)播放列表的成员资格2)艺术家姓名3)字符串搜索4)歌曲名称等

但是,如果文件名被更改,移动,甚至添加到我的音乐目录,我需要能够反映出这是在我的音乐组织引擎中 - 很快!

我原本以为只使用pyinotify,incron或inotify来监视我的目录.不幸的是,我的目录是Samba共享,因此监视文件事件失败.所以我的下一个猜测是简单地在python中递归搜索目录,并填充SQL数据库.然后在更新时,我只想查看是否有任何更改(扫描每个子文件夹以查看每首歌曲的名称是否已在数据库中,如果没有添加),并相应地进行更新.不幸的是,这似乎是一个糟糕的O(n^2)实现 - 对于一个多TB的音乐收藏来说非常糟糕.

稍微好一点的可能涉及在SQL中创建树结构,从而缩小可能的候选者以在任何给定的子文件夹步骤中搜索匹配到该子文件夹的大小.似乎还不够优雅.

我可以使用哪些设计范例/包来帮助自己?显然将涉及许多聪明的哈希表.我只是在寻找正确方向的一些指示,以解决问题.(我也是一个完整的瘾君子.)

Wil*_*ung 3

其中最困难的部分是目录扫描,因为它可能很昂贵。

但这是一个残酷的现实,因为你不能使用 inotify 等。

在您的数据库中,只需创建一个节点类型记录:

create table node (
    nodeKey integer not null primary key,
    parentNode integer references node(nodeKey), // allow null for the root, or have root point to itself, whatever
    fullPathName varchar(2048),
    nodeName varchar(2048),
    nodeType varchar(1) // d = directory, f = file, or whatever else you want
)
Run Code Online (Sandbox Code Playgroud)

这就是你的节点结构。

您可以使用完整路径列通过绝对路径快速查找任何内容。

当文件移动时,只需重新计算路径即可。

最后,扫描您的音乐文件。在 unix 中,你可以执行以下操作:

寻找 。-类型 f | 排序 > 已排序的文件列表

接下来,只需从数据库中提取所有路径名即可。

从节点中选择 fullPathName,其中 nodeType != 'd' 按 fullPathName 排序

现在您有两个排序的文件列表。

通过 DIFF(或 comm)运行它们,您将获得已删除文件和新文件的列表。您不会有“已移动”文件的列表。如果您想做一些启发式的比较新旧文件并且它们具有相同的结尾(即..../album/song)来尝试检测“移动”与新旧文件,那么很好,没什么大不了的。值得一试。

但 diff 会立刻给你你的差异。

如果您有无数的文件,那么,抱歉,这将需要一些时间 - 但当您失去 inotify 功能时您已经知道这一点。如果你有的话,那只是增量维护。

当文件移动时,找到新的绝对路径很简单,因为您可以向其父级询问其路径,然后只需将您的名字附加到其中即可。之后,除非你愿意,否则你就不会爬树或其他任何东西。双向工作。

附加物:

如果您想跟踪实际的名称更改,您可以获得更多信息。

你可以这样做:

find . -type f -print0 | xargs -0 ls -i | sort -n > sortedListOfFileWithInode
Run Code Online (Sandbox Code Playgroud)

-print0 和 -0 用于处理其中包含空格的文件。然而,文件名中的引号会破坏这一点。您最好通过 python 和 fstat 运行原始列表来获取 inode。您可以在这里做不同的事情。

这样做的目的不仅仅是获得名称,还可以获得文件的索引节点。索引节点是“真实”文件,目录将名称链接到索引节点。这就是如何在 unix 文件系统中将多个名称(硬链接)指向单个文件,所有名称都指向同一个 inode。

当文件被重命名时,inode 将保持不变。在 unix 中,有一个用于重命名和移动文件的命令 mv。当 mv 重命名或移动文件时,只要文件位于同一文件系统上,inode 就会保持不变。

因此,使用索引节点和文件名将使您捕获一些更有趣的信息,例如文件移动。

如果他们删除该文件并添加新文件也无济于事。但是您(可能)能够知道它发生了,因为旧的 inode 不太可能被新的 inode 重用。

因此,如果您有一个文件列表(按文件名排序):

1234 song1.mp3
1235 song2.mp3
1236 song3.mp3
Run Code Online (Sandbox Code Playgroud)

有人删除并添加回歌曲 2,你会得到类似的内容

1234 song1.mp3
1237 song2.mp3
1236 song3.mp3
Run Code Online (Sandbox Code Playgroud)

但如果你这样做:

mv song1.mp3 song4.mp3
Run Code Online (Sandbox Code Playgroud)

你会得到:

1237 song2.mp3
1236 song3.mp3
1234 song4.mp3
Run Code Online (Sandbox Code Playgroud)

另一个需要注意的是,如果您丢失了驱动器并从备份中恢复它,则所有索引节点可能都会发生变化,从而强制有效地重建索引。

如果您真正喜欢冒险,您可以尝试使用扩展文件系统属性并将其他有趣的元数据分配给文件。没有做太多的事情,但它也有可能性,并且可能存在看不见的危险,但是......