我們經常會看到文件名和文件夾名。大多數時候文件/文件夾的名字和內容相關並以數字和字母開頭。字母加數字的文件名最常見,應用也很廣泛,但總會需要處理一些包含特殊字符的文件名/文件夾名。
注意:我們可能有各種類型的文件,但是為了簡單以及方便實現,在本文中我們只用文本文件(.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 ./-*
重要:
上面討論的規則可以同樣應用於名字中包含任意數量以及任意位置的連接符號的文件。就是說,-a-b-c.txt,ab-c.txt,abc-.txt,等等。
上面討論的規則可以同樣應用於名字中包含任意數量以及任意位置連接符號的文件夾,除了一種情況,在刪除一個文件夾的時候你得這樣使用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 下會有差異。
譯文:https://linux.cn/article-5777-1.html