我对系统 Fedora 12 中的单个纯文本文件的问题感到完全困惑。我使用了生物信息学领域的一个已知软件,Maker,来生成大量纯文本文件,其中一个似乎“无法访问”。
Clon1918K_PCC1.gff
特别是,当我使用 ... 命令时,会列出我的文件,ls, ls -a, ls -li
但是当我尝试通过cat, vim, cp, ls
etc 访问它时,它总是出现相同的错误Clon1918K_PCC1.gff: No such file or directory
。
但是,当我复制所有文件cp *.gff
或cp *
该文件时,它也会被复制。
我还尝试用 nautilus 打开它,没有出现问题,在两种情况之一中,当我将内容复制到另一个同名文件时,问题消失了。有趣的是,在这种情况下,奇怪的文件没有被重写,并且出现了 2 个具有完全相同名称的文件,其中一个可访问,另一个不可访问。我寻找隐藏的角色,但一切似乎都很好。
有人对这个奇怪的案件有任何想法吗?谢谢!
答案1
同一目录中不能有两个同名的文件。根据定义,文件名是唯一的键。
你所拥有的几乎肯定是一个特殊的角色。我知道你检查过它们,但具体是怎么检查的呢?你可以说类似ls *gff | hexdump -C
查找特殊字符在哪里。任何具有高位设置的字节(即80
和之间的十六进制值FF
)都将指示出现问题。以下任何内容20
(十进制 32)也是特殊字符。另一个提示是.
的右侧文本列中存在点hexdump -C
。
有许多字符在 UTF-8 中看起来像 US ASCII 字符。即使在 US ASCII 中,1 和 l 通常看起来很相似。然后,你有西里尔字母的 C (U+0421)、希腊月牙西格玛 (U+03F9,也完全像 C)、西里尔字母/希腊小写“o”等。这些只是可见的。那里可能有很多不可见的 Unicode 字符。
解释:为什么高位表示出了问题?文件名“Clon1918K_PCC1.gff”似乎是 100% 7 位 US ASCII。把它通过hexdump -C
会产生这样的结果:
00000000 43 6c 6f 6e 31 39 31 38 4b 5f 50 43 43 31 2e 67 |Clon1918K_PCC1.g|
00000010 66 66 |ff|
所有这些字节值都低于0x80
(第 8 位清除),因为它们都是 7 位 US ASCII 代码点。 Unicode 代码点 U+0000 到 U+007F 表示传统的 7 位 US ASCII 字符。代码点 U+0080 及以上代表其他字符,并以 UTF-8 编码为 2 到 6 个字节(在 Linux 上,请尝试man utf8
获取有关如何完成此操作的大量信息)。根据定义,UTF-8 将 US-ASCII 代码点编码为自身(即十六进制 ASCII 字符41
,Unicode U+0041,被编码为单字节41
)。代码点 ≥ 128 被编码为 2 到 6 个字节,每个都设置了第八位。通过此可以轻松检测到非 ASCII 字符的存在无需解码流。例如,假设我将文件名中的第三个字符“o”(ASCII 6f
、U+006F)替换为 Unicode 字符“U+03FB GREEK SMALL LETTER OMICRON”,如下所示:“ο”。hexdump -C
然后产生这个:
00000000 43 6c ce bf 6e 31 39 31 38 4b 5f 50 43 43 31 2e |Cl..n1918K_PCC1.|
00000010 67 66 66 |gff|
第三个字符现在被编码为 UTF-8 序列ce bf
,每个字节都有其第 8 位设置。在这种情况下,这是你遇到麻烦的迹象。另外,请注意hexdump
仅解码 7 位 ASCII 的 ,无法解码单个 UTF-8 字符并显示两个不可打印字符 ( ..
)。
答案2
尝试使用 nautilus 重命名该文件,但键入所需的名称(不要复制粘贴)。这肯定会删除任何特殊字符。它甚至可能是文件名前后的空格,您不可见,但操作系统和程序可见。我通常使用 mc 来处理真正奇怪的文件名。
答案3
您是否考虑过 Rootkit 的存在?曾几何时,我可以访问一台安装了 rootkit 的 Solaris 计算机。名为“*01”的文件在使用ls *01
或 时不可见ls -altr
,但在使用echo *01
. rootkit 的安装ls
(以及许多其他可执行文件)已更改,因此某些文件和进程在通常情况下不会出现。你的描述听起来很像我遇到的rootkit。
答案4
万一有人偶然发现这个并阅读其他答案......你可以跳过很多圈子或像一些答案所说的那样用通配符赌博,或者只是使用ls -b
- 我记得它是“二进制”。
shell 中的制表符补全应自动引用该字符,但您可以使用非 shell 的内容(例如 Nautilus),也可以使用 shell 转义引用样式为ls
其他命令生成方便的预引用字符串。我在其他地方的另一个较长答案中使用了这个奇怪的文件示例,但它在这里也相关:
sauer@lightning:/tmp/test> ls
a??file
sauer@lightning:/tmp/test> ls --quoting-style=shell-escape
'a'$'\t\033''file'
sauer@lightning:/tmp/test> mv -v 'a'$'\t\033''file' regular_filename
renamed 'a'$'\t\033''file' -> 'regular_filename'