![修理东西](https://linux22.com/image/205304/%E4%BF%AE%E7%90%86%E4%B8%9C%E8%A5%BF.png)
例子:
% diff "/Volumes/New Volume/4kyoutube/" "/Volumes/New Volume/tmpmusic"| grep Distortion
Only in /Volumes/New Volume/tmpmusic: ZAC & Bäkka - Distortion (Original Mix) [Sprout].mp3
Only in /Volumes/New Volume/4kyoutube/: ZAC & Bäkka - Distortion (Original Mix) [Sprout].mp3
% diff "/Volumes/New Volume/tmpmusic/ZAC & Bäkka - Distortion (Original Mix) [Sprout].mp3" "/Volumes/New Volume/4kyoutube/ZAC & Bäkka - Distortion (Original Mix) [Sprout].mp3"
%
我能做什么呢?这些文件是相同的。
答案1
这不是“差异误报”,而是两个文件名被视为不同的。
我的大胆假设是,要么这两个文件夹位于不同的设备上,具有不同的文件编码;要么这两个文件夹位于不同的设备上,并且具有不同的文件编码。或者那个这两个名字的编码不同尽管它们在视觉上是相同的。具体来说,两个“Bäkka”之一是“预组合”形式,即 U+00E4 (UTF-8 C3 A4),而另一个是“分解”形式,U+0061 U+0308 (UTF-8 0x61 0xCC) 0x88) 与组合分音符。
我手头没有 MacOS,但我可以在 ext4 Linux 上重现此内容:
$ A=$( echo -e "Ba\xcc\x88kka" )
$ B=$( echo -e "B\xc3\xa4kka" )
$ echo $A $B
Bäkka Bäkka
$ touch $A $B
$ ls -la | grep kka
-rw-rw-rw-+ 1 lserni users 0 Apr 29 18:14 Bäkka
-rw-rw-rw-+ 1 lserni users 0 Apr 29 18:14 Bäkka
显然,我现在在同一个文件夹中有两个同名的文件。
我显然不能确定,但你可能也处于同样的困境。
要进行检查,只需运行“diff”的输出hexdump -C
,看看是否有类似的内容,
00000020 20 20 20 30 20 41 70 72 20 32 39 20 31 38 3a 31 | 0 Apr 29 18:1|
00000030 36 20 42 61 cc 88 6b 6b 61 0a 2d 72 77 2d 72 77 |6 Ba..kka.-rw-rw|
00000060 70 72 20 32 39 20 31 38 3a 31 36 20 42 c3 a4 6b |pr 29 18:16 B..k|
00000070 6b 61 0a |ka.|
请注意,在十六进制转储中,它们立即可见为“Ba..kka”(“a”是普通的“a”,后跟 UTF8“添加分音符”)和“B..kka”(只有一个符号,它是“带分音符号的小拉丁文 a”)。
修理东西
坦率地说,我首先对整个文件夹结构进行规范化。即使您有相同名称的文件,但具有不同的编码(即一些是预组合的,一些是分解的),这迟早会困扰您。
从文件系统的角度来看,您使用哪个系统很大程度上无关紧要。重要的是你现在如何喂养系统以及你现在如何使用系统。
如果新传入的文件具有预组合名称,则将所有 FS 设置为预组合是有意义的(反之亦然),因此将维持标准。另一方面,您可能还想检查搜索文件、排序等功能,以验证文件是否位于您期望的位置(不用说,一些系统认为“a”、“ä”和“ä”相同,而其他一些系统则不然——它们可能将“a”和“ä”设置在一起,“ä”在其他地方;或相反亦然)。
我尝试复制一个名为“älphacomposed”、“älphadecomposed”和“alphaneutral”的小mp3文件,然后使用包含这三个文件以及“alpha0test”和“alphaztest”的文件夹,然后是分解的还是预分解的最好(如果有的话)。
文档似乎表明你应该选择分解的。
首先,您需要所有文件名的列表。这很容易
find . -type f > list-as-it-is.txt
但现在您需要将列表中的预组合元素转换为其分解形式。我做了一些研究,并且,为了增加进一步的复杂性,似乎MacOS 和 Linux 的行为不同,并且 MacOS 存在几个遗留的适应问题:
重要提示:本问答中使用的术语“预组合”和“分解”分别大致对应于 Unicode 范式 C 和 D。然而,大多数卷格式并不遵循这些范式的确切规范。例如,HFS Plus(Mac OS 扩展)使用范式 D 的变体,其中 U+2000 到 U+2FFF、U+F900 到 U+FAFF 以及 U+2F800 到 U+2FAFF 不被分解(这可以避免出现问题)从旧的 Mac 文本编码进行往返转换)。您的卷格式可能也有类似的奇怪之处。
理论上,磁盘上应该只有一种形式(“Mac OS X 的 BSD 层使用规范分解的 UTF-8 编码文件名”)。在实践中,这似乎取决于(显然,否则你不会有问题;可以预见的是,你并不孤单)。
因此,我对于建议转换方法非常谨慎,而无法事先在真正的 MacOS 上进行测试。如果文件很少,那么我建议手动修复它们 - 删除一个文件,将另一个文件复制到另一个文件夹中。
理论上,你可以做类似的事情(在 Bash 中)
hexa=$( echo -n "$name" | xxd -ps | tr -d "\n" )
if [ $[ 2*${#name} ] -lt ${#hexa} ]; then
# Not ASCII.
或 if ( echo "$name" | file - | grep "UTF-8" > /dev/null );然后
如果测试匹配,你可以这样做
mv "$name" "$(dirname "$name")/tmpname" && mv "$(dirname "$name")/tmpname" "$name"
和或许第一个“mv”将识别文件,无论其编码如何,而第二个“mv”将使用固定的默认系统编码重新创建名称,这希望会适合你的。
这种操作会非常快,即使是不必要的处理全部UTF-8 名称。
忽视事物
你可以忽略所有带有这种技巧的文件。那么,只有当两个文件不同,并且具有不同编码的相同名称。这是一个问题吗?如果不是,那么一切都准备好了。
只需进行初步操作grep
,删除包含“^Only”的行:
diff ... | grep -v ^Only | grep Distortion
删除重复项
幸运的是,这完全绕过了编码。已经有一些工具可以做到这jdupes
一点(这是我使用的)。具有相同内容但 MP3 标签不同的文件将无法使用此方法,您可能会发现这个答案有用。
find folder1 -type f -exec md5sum \{\} \; | sort > folder1.txt
find folder2 -type f -exec md5sum \{\} \; | sort > folder2.txt
现在,如果您想获得重复项:
join -o 2.2 folder1.txt folder2.txt
将为您提供folder2中重复的文件(-o 2.1将为您提供folder1中的文件)。
答案2
现在@LSerni 已经发现了这个问题什么是继续下去,你仍然需要处理如何解决它。
显然,一些规范的或至少一致的重命名是最好的。但您可能无法这样做,或者新文件可能会发生这种情况。因此我们需要一个增强的解决方法。
我要做的就是完全避免棘手的 Unicode 问题。
我将通过 sha512() 或其他一些哈希函数(如果需要,递归)运行整个目录。然后,我会用它来识别具有相同内容的文件,即使名称不同。实际上,要么出于 diff 目的人为创建等效的规范文件名(通过符号链接或路径/哈希的编程数组),要么过滤 diff 的输出,要么在多次传递中运行 diff,要么替换您自己的逻辑来报告不确定的文件等效性但事先通过哈希匹配来建议等价物......
换句话说,有很多方法可以做到这一点,而且应该非常简单......但我不能建议哪种方法适合您,因为它不清楚您区分它们的确切目标,也不清楚您的编码技能。