我有 2 个类似的旧目录树,其中包含 MP3 文件。我很高兴使用 diff 和 Rsync 等工具来识别和合并只存在于一侧或相同的文件,剩下一堆按位不同的文件。
在对两个实际上不同的文件运行 diff 时(使用 -a 标签强制进行文本分析),它会产生难以理解的乱码。我听了两边的文件,它们似乎都播放得很好(但每首歌要花将近 10 分钟,每首歌听两遍,我没听多少)
我怀疑这些差异是由于过去某些玩家通过修改 ID3 标签来“增强”我的收藏而造成的,但我不能确定。即使我发现 ID3 标签存在差异,我也想确认没有宇宙射线或文件复制错误问题损坏了任何文件。
想到的一种方法是找到差异的字节位置,并忽略每个文件前~10kb 中的所有更改,但我不知道如何做到这一点。
我有大约一百个左右在目录树中不同的文件。
我发现如何比较文件中的 mp3、flac 音频数据,忽略标题数据(ID3 标签)等?——但由于仅限于 Linux,我无法运行 alldup,而且从声音来看,它只能部分解决我的问题。
答案1
无可比拟根据主题?
Beyond Compare 3 不能在 Linux 上作为控制台应用程序运行。它需要 X-Windows。
支持的 Linux 发行版
红帽企业 Linux 4-6
Fedora 4-14
Novell Suse Linux 企业桌面 10
openSUSE 10.3-11.2
Ubuntu 6.06-10.10
Debian 5.04
曼德里瓦 2010
答案2
Beyond Compare(上面提到)看起来是个不错的解决方案。我从未使用过它。关于 Xwindows 的部分只是意味着它希望在 GUI 中运行,而不是直接在命令行中运行。如果您安装了 GUI,那么 Xwindows 很可能已经正确安装在您的系统上。
关于如何进行的一些想法:
cmp -i 10kB 文件1 文件2
将在 Linux 上按字节比较两个任意文件,首先在每个文件上跳过 10kb。它甚至有一个选项可以跳过每个文件的不同字节数。-b 参数将打印出不同的字节,但这可能是一个很长的输出,因此如果您使用它,请将输出导入文件或 less。您必须决定跳过多少字节。我不知道答案。要有效地将其用于多个文件,您必须用 bash 或其他语言编写脚本。也许将它作为 find 命令的一部分与 exec 选项一起运行会有效。
将来,如果要查找重复文件,请查看 fdupes。这是一个专为此目的而设计的实用程序。当我还在想办法管理计算机上的照片时,我用过它,结果得到了一堆包含大量重复文件的目录。
https://code.google.com/p/fdupes/
另外,如果你在维基百科上查找 fdupes,你会发现条目中列出了大量 Linux 文件比较程序。
只是为了好玩,我看了一下:
http://www.id3.org/id3v2.4.0-structure
它指定了 id3 标签的结构。它“建议”将标签放在文件的开头,但也提供了在文件末尾添加其他标签的功能,因此除非没有人使用该选项,否则文件中的其他地方可能存在元信息,而不仅仅是开头。粗略查看规范会发现 id3 标签信息的长度是可变的,因此没有确切的字节数可以保证跳过它,但最初建议的 10k 应该足以跳过初始标签。
答案3
作为可能的解决方案,您可以使用任何工具将文件转换为不包含元数据信息的未压缩流(pcm
、wav
),然后进行比较。对于转换,您可以使用任何软件,例如ffmpeg
、sox
或avidemux
。
例如我如何使用 ffmpeg
假设我有 2 个具有不同元数据的文件:
$ diff Original.mp3 Possible-dup.mp3 ; echo $? Binary files Original.mp3 and Possible-dup.mp3 differ
强力比较会抱怨它们不同。
然后我们只需转换和区分主体:
$ diff <( ffmpeg -loglevel 8 -i Original.mp3 -map_metadata -1 -f wav - ) <( ffmpeg -loglevel 8 -i Possible-dup.mp3 -map_metadata -1 -f wav - ) ; echo $? 0
当然,这 ; echo $?
部分只是为了演示目的,以查看返回代码。
处理多个文件(遍历目录)
如果您想尝试集合中的重复项,则值得计算数据的校验和(任何如,,,crc
),然后只需找到其中的冲突。md5
sha2
sha256
- 首先计算每个文件中数据的哈希值(并放入文件中进行下一步处理):
for file in *.mp3; do printf "%s:%s\n" "$( ffmpeg -loglevel 8 -i "$file" -map_metadata -1 -f wav - | sha256sum | cut -d' ' -f1 )" "$file"; done > mp3data.hashes
对于您的情况,您可能只比较多个目录,例如:find -L orig-dir dir-with-duplicates -name '*.mp3' -print0 | while read -r -d $'\0' file; do printf "%s:%s\n" "$( ffmpeg -loglevel 8 -i \"$file\" -map_metadata -1 -f wav - | sha256sum | cut -d' ' -f1 )" "$file"; done > mp3data.hashes
文件将如下所示:
$ cat mp3data.hashes ad48913a11de29ad4639253f2f06d8480b73d48a5f1d0aaa24271c0ba3998d02:file1.mp3 54320b708cea0771a8cf71fac24196a070836376dd83eedd619f247c2ece7480:file2.mp3 1d8627a21bdbf74cc5c7bc9451f7db264c167f7df4cbad7d8db80bc2f347110f:Original.mp3 8918674499b90ace36bcfb94d0d8ca1bc9f8bb391b166f899779b373905ddbc1:Other-dup.mp3 8918674499b90ace36bcfb94d0d8ca1bc9f8bb391b166f899779b373905ddbc1:Other.mp3 1d8627a21bdbf74cc5c7bc9451f7db264c167f7df4cbad7d8db80bc2f347110f:Possible-dup.mp3
任何 RDBMS 都非常有用,可以汇总计数并选择此类数据。但继续使用纯命令行解决方案,您可能需要执行进一步的简单步骤。
查看重复的哈希值(如果有)(额外步骤来展示其工作原理,不需要查找重复项):
$ count.by.regexp.awk '([0-9a-f]+):' mp3data.hashes [1:54320b708cea0771a8cf71fac24196a070836376dd83eedd619f247c2ece7480]=1 [1:1d8627a21bdbf74cc5c7bc9451f7db264c167f7df4cbad7d8db80bc2f347110f]=2 [1:ad48913a11de29ad4639253f2f06d8480b73d48a5f1d0aaa24271c0ba3998d02]=1
- 并一起列出按内容重复的文件:
$ grep mp3data.hashes -f <( count.by.regexp.awk '([0-9a-f]+):' mp3data.hashes | grep -oP '(?<=\[1:).{64}(?!]=1$)' ) | sort 1d8627a21bdbf74cc5c7bc9451f7db264c167f7df4cbad7d8db80bc2f347110f:Original.mp3 1d8627a21bdbf74cc5c7bc9451f7db264c167f7df4cbad7d8db80bc2f347110f:Possible-dup.mp3 8918674499b90ace36bcfb94d0d8ca1bc9f8bb391b166f899779b373905ddbc1:Other-dup.mp3 8918674499b90ace36bcfb94d0d8ca1bc9f8bb391b166f899779b373905ddbc1:Other.mp3
按正则表达式计数.awk是awk
一个用于计数正则表达式模式的简单脚本。