Linux 下如何處理包含空格和特殊字元的檔名

Avishek Kumar發表於2015-07-08

我們經常會看到檔名和資料夾名。大多數時候檔案/資料夾的名字和內容相關並以數字和字母開頭。字母加數字的檔名最常見,應用也很廣泛,但總會需要處理一些包含特殊字元的檔名/資料夾名。

注意:我們可能有各種型別的檔案,但是為了簡單以及方便實現,在本文中我們只用文字檔案(.txt)做演示。

最常見的檔名例子:

abc.txt
avi.txt
debian.txt
...

數字檔名例子:

121.txt
3221.txt
674659.txt
...

字母數字檔名例子:

eg84235.txt
3kf43nl2.txt
2323ddw.txt
...

包含特殊字元的檔名的例子,並不常見:

#232.txt
#bkf.txt
#bjsd3469.txt
#121nkfd.txt
-2232.txt
-fbjdew.txt
-gi32kj.txt
--321.txt
--bk34.txt
...

一個顯而易見的問題是 - 在這個星球上有誰會建立和處理包含井號(#),分號(;),破折號(-)或其他特殊字元的檔案/資料夾啊。

我和你想的一樣,這種檔名確實不常見,不過在你必須得處理這種檔名的時候你的 shell 也不應該出錯或罷工。而且技術上來說,Linux 下的一切比如資料夾、驅動器或其他所有的都被當作檔案處理。

處理名字包含破折號(-)的檔案

建立以破折號(-)開頭的檔案,比如 -abx.txt。

$ touch -abc.txt

測試輸出

touch: invalid option -- 'b'
Try 'touch --help' for more information.

出現上面錯誤的原因是,shell 把破折號(-)之後的內容認作引數了,而很明顯沒有這樣的引數,所以報錯。

要解決這個問題,我們得告訴 Bash shell(是的,這裡以及本文後面的大多數例子都是基於 BASH 環境)不要將特殊字元(這裡是破折號)後的字元解釋為引數。

有兩種方法解決這個錯誤:

$ touch -- -abc.txt     [方法 #1]
$ touch ./-abc.txt      [方法 #2]

你可以透過執行命令 ls 或 ls -l 列出詳細資訊來檢查透過上面兩種方式建立的檔案。

$ ls -l

total 0
-rw-r--r-- 1 avi avi 0 Jun  8 11:05 -abc.txt

要編輯上述檔案可以這樣:

$ nano -- -abc.txt 
或者 
$ nano ./-abc.txt 

注意:你可以將 nano 替換為任何其他你喜歡的編輯器比如說 vim:

$ vim -- -abc.txt 
或者 
$ vim ./-abc.txt 

如果只是簡單地移動檔案可以這樣:

$ mv -- -abc.txt -a.txt
或者
$ mv -- -a.txt -abc.txt

刪除這種檔案,可以這樣:

$ rm -- -abc.txt
或者
$ rm ./-abc.txt 

如果一個目錄下有大量這種名字包含破折號的檔案,要一次全部刪除的話,可以這樣:

$ rm ./-*

重要:

  1. 上面討論的規則可以同樣應用於名字中包含任意數量以及任意位置的連線符號的檔案。就是說,-a-b-c.txt,ab-c.txt,abc-.txt,等等。

  2. 上面討論的規則可以同樣應用於名字中包含任意數量以及任意位置連線符號的資料夾,除了一種情況,在刪除一個資料夾的時候你得這樣使用rm -rf

    $ rm -rf -- -abc 或者 $ rm -rf ./-abc

處理名字包含井號(#)的檔案

符號#在 BASH 裡有非常特別的含義。#之後的一切都會被認為是評論,因此會被 BASH 忽略。

透過例子來加深理解:

建立一個名字是 #abc.txt 的檔案:

$ touch #abc.txt

測試輸出

touch: missing file operand
Try 'touch --help' for more information.

出現上面錯誤的原因是,BASH 將 #abc.txt 解釋為評論而忽略了。所以命令 touch沒有收到任何檔案作為引數,所以導致這個錯誤。

要解決這個問題,你可能需要告訴 BASH 不要將 # 解釋為評論。

$ touch ./#abc.txt
或者
$ touch '#abc.txt'

檢查剛建立的檔案:

$ ls -l

total 0
-rw-r--r-- 1 avi avi 0 Jun  8 12:14 #abc.txt

現在建立名字中除了開頭的其他地方包含 # 的檔案。

$ touch ./a#bc.txt
$ touch ./abc#.txt    
或者
$ touch 'a#bc.txt'
$ touch 'abc#.txt'

執行 ‘ls -l‘ 來檢查:

$ ls -l

total 0
-rw-r--r-- 1 avi avi 0 Jun  8 12:16 a#bc.txt
-rw-r--r-- 1 avi avi 0 Jun  8 12:16 abc#.txt

如果同時建立兩個檔案(比如 a 和 #bc)會怎麼樣:

$ touch a.txt #bc.txt

檢查剛建立的檔案:

$ ls -l

total 0
-rw-r--r-- 1 avi avi 0 Jun  8 12:18 a.txt

很明顯上面的例子中只建立了檔案 a 而檔案 #bc 被忽略了。對於上面的情況我們可以這樣做,

$ touch a.txt ./#bc.txt
或者
$ touch a.txt '#bc.txt'

檢查一下:

$ ls -l

total 0
-rw-r--r-- 1 avi avi 0 Jun  8 12:20 a.txt
-rw-r--r-- 1 avi avi 0 Jun  8 12:20 #bc.txt

可以這樣移動檔案:

$ mv ./#bc.txt ./#cd.txt
或者
$ mv '#bc.txt' '#cd.txt'

這樣複製:

$ cp ./#cd.txt ./#de.txt
或者
$ cp '#cd.txt' '#de.txt'

可以使用你喜歡的編輯器來編輯檔案:

$ vi ./#cd.txt
或者
$ vi '#cd.txt'

$ nano ./#cd.txt
或者
$ nano '#cd.txt'

這樣刪除:

$ rm ./#bc.txt 
或者
$ rm '#bc.txt'

要刪除所有以井號(#)開頭的檔案,可以這樣:

# rm ./#*

處理名字包含分號(;)的檔案

如果你還不知道的話,分號在 BASH 裡起到命令分隔的作用,其他 shell 可能也是一樣的。分號作為分隔符可以讓你一次執行幾個命令。你碰到過名字包含分號的檔案嗎?如果沒有的話,這裡有例子。

建立一個名字包含分號的檔案。

$ touch ;abc.txt

測試輸出

touch: missing file operand
Try 'touch --help' for more information.
bash: abc.txt: command not found

出現上面錯誤的原因是,在執行上面命令的時候 BASH 會把 touch 解釋為一個命令但是在分號前沒有任何檔案引數,所以報告錯誤。然後報告的另一個錯誤找不到命令 abc.txt,只是因為在分號後 BASH 會期望另一個新的命令,而 abc.txt 並不是一個命令。

要解決這個問題,我們得告訴 BASH 不要將分號解釋為命令分隔符,例如:

$ touch ./';abc.txt'
或者
$ touch ';abc.txt'

注意:我們將檔名用單引號 '' 包含起來。這樣可以告訴 BASH 分號 ; 是檔名的一部分而不是命令分隔符。

對名字包含分號的檔案和資料夾的其他操作(就是,複製、移動、刪除)可以直接將名字用單引號包含起來就好了。

處理名字包含其他特殊字元的檔案/資料夾

檔名包含加號 (+)

不需要任何特殊處理,按平時的方式做就好了,比如下面測試的檔名。

$ touch +12.txt 

檔名包含美元符 ($)

你需要將檔名用單引號括起來,像處理分號那樣的方式。然後就很簡單了。

$ touch '$12.txt'

檔名包含百分號 (%)

不需要任何特殊處理,當作一個普通檔案就可以了。

$ touch %12.txt

檔名包含星號 (*)

需要用單引號括起來或使用反斜槓轉義。(LCTT 譯註:此處原文有誤,已修改。)

$ touch *12.txt

注意:當你需要刪除星號開頭的檔案時,千萬不要用類似下面的命令。

$ rm *
或者
$ rm -rf *

而是用這樣的命令,(LCTT 譯註:此處原文有誤,已修改)

$ rm ./'*.txt'

檔名包含歎號 (!)

只要將檔名用單引號括起來,其他的就一樣了。

$ touch '!12.txt'

檔名包含小老鼠 (@)

沒有什麼特別的,可以將名字包含小老鼠的檔案當作普通檔案。

$ touch '@12.txt'

檔名包含 ^

不需要特殊處理。可以將名字包含 ^ 的檔案當作普通檔案。

$ touch ^12.txt

檔名包含 (&)

將檔名用單引號括起來,然後就可以操作了。

$ touch '&12.txt'

檔名包含括號 ()

如果檔名包含括號,你需要將檔名用單引號括起來。

$ touch '(12.txt)'

檔名包含花括號 {}

用單引號括起來或使用反斜槓轉義。(LCTT 譯註:此處原文有誤,已修改)

$ touch '{12.txt}'

檔名包含尖括號 <>

名字包含尖括號的檔案需要用單引號括起來。

$ touch '<12.txt>'

檔名包含方括號 [ ]

用單引號括起來或使用反斜槓轉義。(LCTT 譯註:此處原文有誤,已修改)

$ touch '[12.txt]'

檔名包含下劃線 (_)

這個非常普遍,不需要特殊對待。當作普通檔案隨意處理。

$ touch _12.txt

檔名包含等號 (=)

用單引號括起來或使用反斜槓轉義。(LCTT 譯註:此處原文有誤,已修改)

$ touch '=12.txt'

處理反斜槓 ()

反斜槓會告訴 shell 忽略後面字元的特殊含義。你必須將檔名用單引號括起來,就像處理分號那樣。其他的就沒什麼了。

$ touch '\12.txt'

包含斜槓的特殊情形

除非你的檔案系統有問題,否則你不能建立名字包含斜槓的檔案。沒辦法轉義斜槓。

所以如果你能建立類似 ‘/12.txt’ 或者 ‘b/c.txt’ 這樣的檔案,那要麼你的檔案系統有問題,或者支援 Unicode,這樣你可以建立包含斜槓的檔案。只是這樣並不是真的斜槓,而是一個看起來像斜槓的 Unicode 字元。

檔名包含問號 (?)

用單引號括起來或使用反斜槓轉義。(LCTT 譯註:此處原文有誤,已修改)

$ touch '?12.txt'

檔名包含點 (.)

在 Linux 裡以點 (.) 開頭的檔案非常特別,被稱為點檔案。它們通常是隱藏的配置檔案或系統檔案。你需要使用 ls 命令的 ‘-a‘ 或 ‘-A‘ 開關來檢視這種檔案。

建立,編輯,重新命名和刪除這種檔案很直接。

$ touch .12.txt

注意:在 Linux 裡你可能碰到名字包含許多點 (.) 的檔案。不像其他作業系統,檔名裡的點並不意味著分隔名字和擴充套件字尾。你可以建立名字包含多個點的檔案:

$ touch 1.2.3.4.5.6.7.8.9.10.txt

檢查一下:

$ ls -l

total 0
-rw-r--r-- 1 avi avi 0 Jun  8 14:32 1.2.3.4.5.6.7.8.9.10.txt

檔名包含逗號 (,)

你可以在檔名中使用逗號,可以有任意多個而不用特殊對待。就像平時普通名字檔案那樣處理。

$ touch ,12.txt
或者
$ touch ,12,.txt

檔名包含冒號 (:)

用單引號括起來或使用反斜槓轉義。(LCTT 譯註:此處原文有誤,已修改)

$ touch ':12.txt'
或者
$ touch ':12:.txt'

檔名包含引號(單引號和雙引號)

要在檔名裡使用引號,我們需要使用交替規則。例如,如果你需要在檔名裡使用單引號,那就用雙引號把檔名括起來。而如果你需要在檔名裡使用雙引號,那就用單引號把檔名括起來。(LCTT 譯註:或者如果單引號和雙引號混雜的情況,你也可以用反斜槓轉義。)

$ touch "15'.txt"

以及

$ touch '15".txt'

檔名包含波浪號 (~)

Linux 下一些像 emacs 這樣的文字編輯器在編輯檔案的時候會建立備份檔案。這個備份檔案的名字是在原檔名後面附加一個波浪號。你可以在檔名任意位置使用波浪號,例如:

$ touch ~1a.txt
或者
$touch 2b~.txt

檔名包含空格

建立名字的字元/單詞之間包含空格的檔案,比如 “hi my name is avishek.txt”。

最好不要在檔名裡使用空格,如果你必須要分隔可讀的名字,可以使用下劃線或橫槓。不過,你還是需要建立這樣的檔案的話,你可以用反斜槓來轉義下一個字元。要建立上面名字的檔案可以這樣做。

$ touch hi\ my\ name\ is\ avishek.txt

hi my name is avishek.txt

我已經嘗試覆蓋你可能碰到的所有情況。上面大多數測試都在 BASH Shell 裡完成,可能在其他 shell 下會有差異。

如果你覺得我遺漏了什麼(這很正常也符合人性),請把你的建議發表到下面的評論裡。保持聯絡,多評論。不要走開!求點贊求分享求擴散!


via: http://www.tecmint.com/manage-linux-filenames-with-special-characters/

作者:Avishek Kumar 譯者:zpl1025 校對:wxy

本文由 LCTT 原創翻譯,Linux中國 榮譽推出

相關文章