Linux 下如何处理包含空格和特殊字符的文件名
================================================================================
我们经常会看到文件名和文件夹名。大多数时候文件/文件夹的名字和内容相关并以数字和字母开头。字母加数字的文件名最常见，应用也很广泛，但总会需要处理一些包含特殊字符的文件名/文件夹名。

** 注意 **：我们可能有各种类型的文件，但是为了简单以及方便实现，在本文中我们只用文本文件（.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][1] 列出详细信息来检查通过上面两种方式创建的文件。

    $ 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][2]没有收到任何文件作为参数，所以导致这个错误。

要解决这个问题，你可能需要告诉 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][a]
译者：[zpl1025](https://github.com/zpl1025)
校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创翻译，[Linux中国](https://linux.cn/) 荣誉推出

[a]:http://www.tecmint.com/author/avishek/
[1]:https://linux.cn/article-5349-1.html
[2]:http://www.tecmint.com/8-pratical-examples-of-linux-touch-command/
