AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 700865
Accepted
Niklas Rosencrantz
Niklas Rosencrantz
Asked: 2022-04-30 07:49:45 +0800 CST2022-04-30 07:49:45 +0800 CST 2022-04-30 07:49:45 +0800 CST

diff 程序对文件名中包含非 ASCII 字符的文件给出误报

  • 772

例子:

% 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" 
% 

我能做些什么呢?这些文件是相同的。

diff macos
  • 2 2 个回答
  • 340 Views

2 个回答

  • Voted
  1. Best Answer
    LSerni
    2022-04-30T08:21:22+08:002022-04-30T08:21:22+08:00

    这不是“差异误报”,而是两个文件名被视为不同的.

    我的疯狂假设是这两个文件夹位于不同的设备上,具有不同的文件编码;或者这两个名称的编码不同,尽管它们在视觉上是相同的。具体来说,两个“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”(只有一个符号,它是“带有分音符号的小拉丁语”)。

    修理东西

    坦率地说,我会首先对整个文件夹结构进行规范化。即使您有相同名称的文件,但使用不同的编码(即一些预先组合,一些分解),这迟早会咬你。

    从文件系统的角度来看,您使用哪个系统在很大程度上是无关紧要的。重要的是你现在如何喂养系统以及你现在如何使用系统。

    如果新传入的文件具有预先组合的名称,则将所有 FS 设置为预先组合(反之亦然)是有意义的,因此将保持标准。另一方面,您可能还想查看搜索文件、排序等功能,以验证文件是否在您期望的位置(不用说,某些系统会考虑“a”、“ä " 和 "ä" 相同,有些则不同 - 他们可能将 "a" 和 "ä" 放在一起,将 "ä" 放在其他位置;反之亦然)。

    我会尝试复制一个名为“älphacomposed”、“älpha decomposed”和“alpha中性”的小型mp3文件,然后使用包含这三个文件以及“alpha 0 test”和“alpha z test”的文件夹,然后是分解还是预分解是最好的,如果有的话。

    文档似乎表明您应该使用 decomposed。

    所以首先,你需要一个所有文件名的列表。这很简单

    find . -type f > list-as-it-is.txt
    

    但是现在您需要将列表中的预组合元素转换为它们的分解形式。我做了一些研究,为了增加更复杂的一层, MacOS 和 Linux 的行为似乎不同,而且 MacOS 有几个遗留问题:

    重要提示:本问答中使用的术语,precomposed 和 decomposed,大致分别对应于 Unicode 范式 C 和 D。但是,大多数卷格式不遵循这些标准格式的确切规范。例如,HFS Plus (Mac OS Extended) 使用 Normal Form 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”将识别文件,无论其编码如何,而第二个将使用固定的默认系统编码重新创建名称,希望适合您。

    这种操作会非常快,即使它不必要地处理所有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
    

    将为您获取文件夹 2 中重复的文件(-o 2.1 将为您获取文件夹 1 中的文件)。

    • 10
  2. Stilez
    2022-04-30T17:09:53+08:002022-04-30T17:09:53+08:00

    既然@LSerni 已经发现了正在发生的事情的问题,您仍然需要处理如何解决它。

    显然,一些规范的或至少一致的重命名是最好的。但是您可能无法做到,或者新文件可能会发生这种情况。所以我们需要一个增强的解决方法。

    我要做的是完全避免棘手的 Unicode 问题。

    我会通过 sha512() 或其他一些散列函数(必要时递归)运行整个目录。然后,即使名称不同,我也会使用它来识别具有相同内容的文件。实际上,要么为 diff 目的人为地创建等效的规范文件名(通过符号链接或路径/哈希的编程数组),要么过滤 diff 的输出,或者在多遍中运行 diff,或者替换您自己的逻辑来报告不确定的文件等效性但事先通过哈希匹配以建议等价物.....

    换句话说,有很多方法可以做到这一点,而且应该很容易......但我不能建议哪种方法适合你,因为它不清楚你区分它们的确切目标,也不清楚你的编码技能。

    • 3

相关问题

  • 两个目录的差异文件名?

  • 将 diff -e 的输出与 sed 一起使用

  • 仅显示未注释行的配置文件的差异

  • 确定两个 iso 图像是否相等

  • git:仅在 GUI 中使用视觉差异(融合)

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    模块 i915 可能缺少固件 /lib/firmware/i915/*

    • 3 个回答
  • Marko Smith

    无法获取 jessie backports 存储库

    • 4 个回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    user12345 无法获取 jessie backports 存储库 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl 为什么大多数 systemd 示例都包含 WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve