奇怪的情況:文字檔案存在與不存在

奇怪的情況:文字檔案存在與不存在

我對我的系統 Fedora 12 中的單一純文字文件的問題感到完全困惑。

Clon1918K_PCC1.gff特別是,當我使用 ... 命令時,會列出我的文件,ls, ls -a, ls -li但是當我嘗試透過cat, vim, cp, lsetc 存取它時,它總是出現相同的錯誤Clon1918K_PCC1.gff: No such file or directory

但是,當我複製所有文件cp *.gffcp *該文件時,它也會被複製。

我還嘗試用 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'

相關內容