删除名称中有特殊字符的文件

问题

在 Linux 下用命令行来删除文件是极为常用的操作,然后有时候会遇到文件名称为特殊字符的情况,使用普通的 rm <filename> 的方式无法对其执行删除。代表性的,像这些特殊字符: - -- ; & $ ? * \
以如下文件为例:

# ls -l
total 0
-rw-r--r-- 1 apporc apporc 0 Dec 14 20:54 file
-rw-r--r-- 1 apporc apporc 0 Dec 14 20:55 >file
-rw-r--r-- 1 apporc apporc 0 Dec 14 20:54 -file
-rw-r--r-- 1 apporc apporc 0 Dec 14 20:55 --file
-rw-r--r-- 1 apporc apporc 0 Dec 14 20:56 !@#$%^&*file
-rw-r--r-- 1 apporc apporc 0 Dec 14 20:56 * file
-rw-r--r-- 1 apporc apporc 0 Dec 14 21:16 \file
-rw-r--r-- 1 apporc apporc 0 Dec 14 20:57 my file.txt

尝试删除它们会报各种错误:

[apporc@arch-server test] > rm >file
rm: missing operand
Try 'rm --help' for more information.
[apporc@arch-server test] > rm -file
rm: invalid option -- 'l'
Try 'rm ./-file' to remove the file ‘-file’.
Try 'rm --help' for more information.
[apporc@arch-server test] > rm --file
rm: unrecognized option '--file'
Try 'rm ./--file' to remove the file ‘--file’.
Try 'rm --help' for more information.
[apporc@arch-server test] > rm !@#$%^&*file
bash: !@#$%^: event not found
[apporc@arch-server test] > rm * file
rm: invalid option -- 'l'
Try 'rm ./-file' to remove the file ‘-file’.
Try 'rm --help' for more information.
[apporc@arch-server test] > rm my file.txt
rm: cannot remove ‘my’: No such file or directory
rm: cannot remove ‘file.txt’: No such file or directory

原因

发生以上情况的原因,一者由于 Linux 所使用的 shell 程序(通常是 bash, ksh 等)对特殊字符有特别的解释。最明显的,-对于一般命令来说都代表着命令参数,&对于 bash 来说是启动后台任务的符号。

解决方法

针对不同的特殊字符,应对方式也会有所不同。主要有下面几种:
1.使用引号

首先是空格,文件名为有空格的情况,即可以解决

# rm "my file.txt"
removed ‘my file.txt’

另外把文件名放在引号之中,也可以防止很多特殊字符被 shell 或者命令本身解释作特殊用途,例如:

rm -v ">file"
removed ‘>file’

双引号可以把除 $ \ 以及反引号之外的特殊字符都封闭起来。对于这些更特殊的情况,也可以试试单引号。
2.使用反斜线

对于某些特殊字符,在其前面插入一个反斜线,有时即可解决问题。如

# rm -v \\file
removed ‘\\file’

3.在文件名前加上./

有一些情况,使用以上两种方法,都不能解决,比如-file

# > rm -v \-file
rm: invalid option -- 'l'
Try 'rm ./-file' to remove the file ‘-file’.
Try 'rm --help' for more information.
# > rm -v '-file'
rm: invalid option -- 'l'
Try 'rm ./-file' to remove the file ‘-file’.
Try 'rm --help' for more information.

而使用本方法,则可以解决。

# rm -v ./-file 
removed ‘./-file’

./的含义指“当前目录下”,可能成功将文件名中的-跳脱开来,使其不再作为“选项前缀”来解释。

4.在文件名称前加上--
--等于告知 shell 从它起始,命令选项已经结束,后续出现的字符都作为文件名或者参数。
使用格式如下:

# rm -v -- --file
removed ‘--file’

5.根据文件的 inode 来删除文件
此方法可谓大杀器,不再纠结于哪个符号怎么处理,绕过表面从根本上来解决问题。操作步骤如下:

  • 使用 ls -li 来查看文件的 inode 号

    208 -rw-r--r-- 1 apporc apporc 0 Dec 14 20:59 file
    211 -rw-r--r-- 1 apporc apporc 0 Dec 14 20:56 !@#$%^&*file
    212 -rw-r--r-- 1 apporc apporc 0 Dec 14 20:56 * file
    
  • 使用 find -inum <inode number> -delete 来指定 inode 号删除文件

    #find -inum 211 -delete
    

    或者

    #find -inum 211 -exec rm -i {} \;