[英]Mac OSX terminal folder names with special characters
我最近切换到MAC OSX,在终端中创建包含特殊字符的目录时遇到了问题。
基本上会发生什么:
Finder
创建目录té$t
并在其中复制文件时,可以在终端和Finder中访问它 当我在终端中创建相同的目录té$ t并在其中放置文件时,我可以在终端中对其进行访问,在Finder中,我收到一个错误,指出找不到该文件。 在终端中重命名没有特殊字符的目录时,我可以在Finder中访问文件。
:> locale LANG= LC_COLLATE="C" LC_CTYPE="UTF-8" LC_MESSAGES="C" LC_MONETARY="C" LC_NUMERIC="C" LC_TIME="C" LC_ALL=
这一定是某种编码方式,对吗?
更新:
忘记$,而只使用é(或其他任何áìç等)。 该文件夹已创建,只是在终端中创建文件夹时我无法访问其中的任何文件
在unicode中,重音字符(例如é)通常可以用两种不同的方式表示:“预分解”为代表重音字母的单个代码点,或“分解”为代表未重音字母后跟组合重音的一系列代码点(或甚至不止一个...)。 在“é”的情况下,其预分解形式为U + 00e9 = UTF-8 0xc3a9 =“带有重音符号的拉丁文小写字母e”,其分解形式为U + 0065 U + 0301 = UTF-8 0x65cc81 = “拉丁小写字母e” +“组合重音符号”。
在终端中输入文件名时,您是以预组合形式输入文件名的; 但Mac OS扩展文件系统以分解形式存储文件名(此处不涉及某些例外)。 当您指定文件名中包含预组合字符时,文件系统将对其进行分解以进行存储。 最终结果:当您以后尝试使用该文件时,您尝试使用的名称与该文件的实际名称相同但不相同的名称进行访问。 根据您访问它的方式的不同,是否正确处理等效项,因此可能会或可能不会找到文件。
通常,文件系统会像这种权限一样处理等效项,但Shell和其他程序不知道文件系统编码的详细信息,因此会出错。 因此,如果外壳程序/其他程序只是将名称传递给文件系统代码,则它可以工作,但是如果外壳程序/其他程序试图弄清楚文件本身是否存在,它将失败。 例如, touch "tést"; [ -e "tést" ]
touch "tést"; [ -e "tést" ]
使用文件系统来查找“tést”是否存在,并将找到它; 但是té
制表符té
全由外壳处理,并且会失败。 看到这个apple.se问题 。
我无法在Mac上重现您的问题,但是我并没有按照您的方式来处理我的语言环境。
$ mkdir weird
$ cd weird
$ mkdir naïve résumé touché
$ for d in *; do cp ../q7.c $d/$d.c; done
$ ls -l *
naïve:
total 8
-rw-r----- 1 jleffler staff 990 Nov 19 07:30 naïve.c
résumé:
total 8
-rw-r----- 1 jleffler staff 990 Nov 19 07:30 résumé.c
touché:
total 8
-rw-r----- 1 jleffler staff 990 Nov 19 07:30 touché.c
$ locale
LANG="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_CTYPE="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_ALL=
$
我碰巧在文件q7.c
有一些来源; 这创建了一系列“重音”目录,每个目录都包含一个重音文件。 命令行工具没有问题。
我认为这是我只能用图像演示的地方:
这应该表明Finder正在查看naïve
文件夹中的文件naïve.c
。 我能够在Finder中单击文件,并且它运行了XCode:
首先,尝试将您的语言环境设置为en_US.UTF-8
,看看是否有任何区别。
如果确实如此,那么我假设您正在使用Latin 1创建文件名,但是Finder使用UTF-8运行。 麻烦的是,您的文件名不是有效的UTF-8文件名。 这可能会使Finder无法正常工作。
这是一个尝试滥用系统的程序:
#include <sys/stat.h>
#include <stdio.h>
int main(void)
{
char name[] = "\xC0\xC1\xC2\xC3\xC4\xC5\xC6";
char file[] = "weird.c";
/*
C0 U+00C0 LATIN CAPITAL LETTER A WITH GRAVE
C1 U+00C1 LATIN CAPITAL LETTER A WITH ACUTE
C2 U+00C2 LATIN CAPITAL LETTER A WITH CIRCUMFLEX
C3 U+00C3 LATIN CAPITAL LETTER A WITH TILDE
C4 U+00C4 LATIN CAPITAL LETTER A WITH DIAERESIS
C5 U+00C5 LATIN CAPITAL LETTER A WITH RING ABOVE
C6 U+00C6 LATIN CAPITAL LETTER AE
*/
if (mkdir(name, 0755) != 0)
{
fprintf(stderr, "mkdir(%s) failed\n", name);
return(1);
}
char buffer[32];
snprintf(buffer, sizeof(buffer), "%s/%s.c", name, name);
FILE *ofp = fopen(name, "w");
if (ofp == 0)
{
fprintf(stderr, "fopen(%s) failed\n", buffer);
return(1);
}
FILE *ifp = fopen(file, "r");
if (ifp == 0)
{
fprintf(stderr, "fopen(%s) failed\n", file);
return(1);
}
size_t nbytes;
while ((nbytes = fread(buffer, 1, sizeof(buffer), ifp)) != 0)
fwrite(buffer, 1, nbytes, ofp);
fclose(ifp);
fclose(ofp);
return 0;
}
您可能知道,字节0xC0和0xC1永远不会出现在格式正确的UTF-8中。 其他字节是2字节UTF-8字符的合法起始字节,但随后的字节应始终在0x80..0xAF范围内。 显然,名称不是格式正确的UTF-8。
Osiris JL: make weird
gcc -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition -Werror weird.c -o weird
Osiris JL: ls -l
total 40
-rw-r----- 1 jleffler staff 1629 Nov 19 07:54 makefile
drwxr----- 4 jleffler staff 136 Nov 19 07:36 naïve
drwxr----- 4 jleffler staff 136 Nov 19 07:36 résumé
drwxr----- 4 jleffler staff 136 Nov 19 07:36 touché
-rwxr----- 1 jleffler staff 9068 Nov 19 08:00 weird
-rw-r----- 1 jleffler staff 1142 Nov 19 07:59 weird.c
drwxr----- 3 jleffler staff 102 Nov 19 08:00 weird.dSYM
Osiris JL: ./weird
fopen(???????/???????.c) failed
Osiris JL: ls -l
total 40
drwxr----- 2 jleffler staff 68 Nov 19 08:00 %C0%C1%C2%C3%C4%C5%C6
-rw-r----- 1 jleffler staff 1629 Nov 19 07:54 makefile
drwxr----- 4 jleffler staff 136 Nov 19 07:36 naïve
drwxr----- 4 jleffler staff 136 Nov 19 07:36 résumé
drwxr----- 4 jleffler staff 136 Nov 19 07:36 touché
-rwxr----- 1 jleffler staff 9068 Nov 19 08:00 weird
-rw-r----- 1 jleffler staff 1142 Nov 19 07:59 weird.c
drwxr----- 3 jleffler staff 102 Nov 19 08:00 weird.dSYM
Osiris JL: rmdir *C6
Osiris JL: ./weird 2>&1 | odx
0x0000: 66 6F 70 65 6E 28 C0 C1 C2 C3 C4 C5 C6 2F C0 C1 fopen(......./..
0x0010: C2 C3 C4 C5 C6 2E 63 29 20 66 61 69 6C 65 64 0A ......c) failed.
0x0020:
Osiris JL:
因此,我可以按照某种方式创建目录,但是可以使用rmdir *C6
将其删除。 这个名字不是我所期望的。 无法创建该文件。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.