BASH查找名称中带有ñ的文件

时间:2018-07-15 00:24:35

标签: regex bash find quoting

已经尝试了多种解决方案,但似乎都没有用。

例如,如果我尝试下一个命令,它将按预期工作

/** @typedef {import('./Core').default} Core */

export default class Engine{
    /** @type {Core} core */
    constructor(core) {
        /** @type {Core} */            
        this.core = core;
    }
}

它返回:

./ alphabet / output / b / box.jpg

./ alphabet / output / t / taxi.jpg

但是如果我尝试使用西班牙语字母中的任何特殊字符,该命令将无效

find . -type f -name *x*

结果为空。

如果我尝试

find . -type f -name *ñ*

然后它还会显示带有特殊字符ñ

的文件名

如果我尝试为命令设置LANG变量,它也将不起作用

find . -type f -name *n*

或使用正则表达式

LANG=C find . -type f -name *ñ*

1 个答案:

答案 0 :(得分:2)

(其中一部分是从previous answer of mine中盗取的。)

Unicode允许某些重音字符以几种不同的方式表示:作为表示重音字符的“代码点”,或作为表示字符的无重音版本的一系列代码点,后跟重音。例如,“?”既可以表示为U + 00F1(UTF-8 0xc3b1,带小号的拉丁小写字母n),也可以表示为U + 006E U + 0303(UTF-8 0x6ecc83,带小写的n +组合小写字母) )。

OS X的HFS +文件系统要求所有文件名都以其完全分解的形式的UTF-8表示形式存储(此处不涉及一些例外)。在HFS +文件名中,“ñ”必须编码为0x6ecc83。

当您在键盘上键入“ñ”时,它将使用U + 00F1(0xc3b1)的组合形式。您可以通过十六进制转储看到它:

$ echo ñ | xxd
00000000: c3b1 0a                                  ...

(请注意:“ {0a””是echo输出的“行”末尾的换行符。)但是,当在MacOS Extended卷上的文件名中使用它时,它将转换为分解成U + 006E U + 0303(0x6ecc83):

$ touchñ $ ls | xxd 00000000:6ecc 830a n ...

在UTF-8语言环境中,应将这两种不同的表示形式视为同一字符,但显然macOS中的find不能正确执行此操作:

$ LC_ALL=en_US.UTF-8 find . -name '*ñ*'
$ LC_ALL=en_US.UTF-8 find . -name '*n*'
./ñ
$ LC_ALL=en_US.UTF-8 find . -name 'n?'
./ñ

在第二个和第三个命令中,find与“ n”代码点匹配,并将合并代字号视为跟在其后的一个完全独立的字符。顺便说一句,请注意我在匹配模式周围加上了引号-这很重要,因为没有它们,shell会将其扩展到当前目录中的文件名列表,然后传递给find命令。

解决方案?好吧,这里有一个棘手的选项,可以在模式中显式地使用分解后的形式。您可以使用bash的$' ... '引用形式来执行此操作,该形式允许使用\x指定十六进制字节:

$ find . -name $'*n\xcc\x83*'
./ñ

但是实际上,这甚至更糟,因为从macOS High Sierra开始,苹果使用了新的苹果文件系统(APFS),该文件系统允许两种表示形式。而且由于find不能将它们识别为字符,所以您甚至不能使用像-name *[ññ]*' to match both of them, you have to use an extended regular expression with-E and-regex`这样的括号表达式(在带有APFS的Mac上完成):

$ touch composed-ñ decomposed-n$'\xcc\x83' unaccented-n
$ ls
composed-ñ  decomposed-ñ    unaccented-n
$ ls | xxd
00000000: 636f 6d70 6f73 6564 2dc3 b10a 6465 636f  composed-...deco
00000010: 6d70 6f73 6564 2d6e cc83 0a75 6e61 6363  mposed-n...unacc
00000020: 656e 7465 642d 6e0a                      ented-n.
$ find -E . -regex $'.*(\xc3\xb1|n\xcc\x83).*'
./composed-ñ
./decomposed-ñ

(请注意,在正则表达式中,.*是匹配任何字符序列的方式,等效于普通“ glob”通配符模式中的*。)

您自己的Unicode支持不是很有趣吗?