rm 命令详解与参数实测(Ubuntu 22.04)

GNU rm 参数实测:-r/-f/-i/-I/-d/-v 逐项行为、退出码与 rm -rf / 的根目录失败保护,Ubuntu 22.04 实测。

Linux命令Linux系统UbuntuUbuntu 22.04命令行文件管理2026/10/15

rm 命令详解与参数实测(Ubuntu 22.04)

目标:全面掌握 GNU rm 的常用参数——默认删除、-r 递归、-f 静默强删(不存在文件也成功)、-i 逐个确认、-I 超 3 个文件一次性确认、-v 过程显示、-d 删空目录,以及 rm -rf / 的根目录失败保护机制,全部命令与回显已在 Ubuntu 22.04(GNU coreutils 8.32)实测通过。

⚠️ 危险操作提示:rm 删除不可逆(无回收站)。生产环境执行 -r、-f、通配符组合命令前,务必先核对路径与匹配范围;本文所有删除动作都在专用演示目录 /root/demo/rm/ 内进行。

一、环境信息

本篇所有命令与回显均来自同一台 Ubuntu 22.04 服务器的实测,演示数据统一放在 /root/demo/rm/ 下,读者在任意 Ubuntu 22.04 机器上按相同步骤均可复现。

  • 操作系统:Ubuntu 22.04.5 LTS(x86_64)
  • rm 版本:GNU coreutils 8.32(rm --version 实测)
  • rm 属于 coreutils 基础工具集,Ubuntu 22.04 默认预装,无需额外安装
  • 演示目录:/root/demo/rm/
  • 测试数据:若干空文件(f1、f2、a1、a2、g1、g2、q1、q2、q3、p1、p2、p3、p4、v1)、含子目录的 dir1/、非空目录 dir2/、空目录 empty3

二、命令概览

2.1 语法与测试数据准备

rm 的语法为 rm [OPTION]... [FILE]...(摘自帮助 Usage 行),职责是删除(unlink)文件;默认不删目录,删目录必须加 -r。

💡 技术拓展:"删除一个文件/目录"有几种不同方式,破坏力与防护各不相同,横向对比——

方式原理/职责适用场景
rmunlink 文件;-r 递归删目录树日常删除,默认首选
rmdir只能删空目录,非空即报错作为误删防护网的安全删除
unlink删单个文件/软链,无递归无选项脚本里单文件精确删除
shred多次覆写数据块后再删除需防止内容被专业手段恢复

本文主角是 rm:能力最强也最危险,交互确认(-i/-I)与 root 保护(--preserve-root)是两大安全阀,分别见 3.4/3.5 与 3.8 实测。

为了让 -I 的"超过 3 个文件"阈值可实测,准备了一批编号空文件:

mkdir -p /root/demo/rm/dir1/sub /root/demo/rm/dir2 /root/demo/rm/empty3
printf 'one\n' > /root/demo/rm/f1.txt
: > /root/demo/rm/f2.txt
: > /root/demo/rm/a1.txt
: > /root/demo/rm/a2.txt
: > /root/demo/rm/g1.txt
: > /root/demo/rm/g2.txt
: > /root/demo/rm/q1.txt
: > /root/demo/rm/q2.txt
: > /root/demo/rm/q3.txt
: > /root/demo/rm/p1.txt
: > /root/demo/rm/p2.txt
: > /root/demo/rm/p3.txt
: > /root/demo/rm/p4.txt
: > /root/demo/rm/v1.txt
: > /root/demo/rm/dir1/sub/deep.txt
printf 'keep\n' > /root/demo/rm/dir2/keep.txt

验证数据就绪:

$ ls -l /root/demo/rm
total 16
-rw-r--r-- 1 root root    0 Oct 15 06:35 a1.txt
-rw-r--r-- 1 root root    0 Oct 15 06:35 a2.txt
drwxr-xr-x 3 root root 4096 Oct 15 06:35 dir1
drwxr-xr-x 2 root root 4096 Oct 15 06:35 dir2
drwxr-xr-x 2 root root 4096 Oct 15 06:35 empty3
-rw-r--r-- 1 root root    4 Oct 15 06:35 f1.txt
-rw-r--r-- 1 root root    0 Oct 15 06:35 f2.txt
-rw-r--r-- 1 root root    0 Oct 15 06:35 g1.txt
-rw-r--r-- 1 root root    0 Oct 15 06:35 g2.txt
-rw-r--r-- 1 root root    0 Oct 15 06:35 p1.txt
-rw-r--r-- 1 root root    0 Oct 15 06:35 p2.txt
-rw-r--r-- 1 root root    0 Oct 15 06:35 p3.txt
-rw-r--r-- 1 root root    0 Oct 15 06:35 p4.txt
-rw-r--r-- 1 root root    0 Oct 15 06:35 q1.txt
-rw-r--r-- 1 root root    0 Oct 15 06:35 q2.txt
-rw-r--r-- 1 root root    0 Oct 15 06:35 q3.txt
-rw-r--r-- 1 root root    0 Oct 15 06:35 v1.txt

17 个条目(14 个文件、3 个目录)就位,dir2 里有 keep.txt(非空),dir1 里嵌套 sub/deep.txt(供 -r 观察递归过程)。

2.2 --help 全量回显

rm --help 输出全部参数清单(实测原样保留,可作为参数速查):

Usage: rm [OPTION]... [FILE]...
Remove (unlink) the FILE(s).

  -f, --force           ignore nonexistent files and arguments, never prompt
  -i                    prompt before every removal
  -I                    prompt once before removing more than three files, or
                          when removing recursively; less intrusive than -i,
                          while still giving protection against most mistakes
      --interactive[=WHEN]  prompt according to WHEN: never, once (-I), or
                          always (-i); without WHEN, prompt always
      --one-file-system  when removing a hierarchy recursively, skip any
                          directory that is on a file system different from
                          that of the corresponding command line argument
      --no-preserve-root  do not treat '/' specially
      --preserve-root[=all]  do not remove '/' (default);
                              with 'all', reject any command line argument
                              on a separate device from its parent
  -r, -R, --recursive   remove directories and their contents recursively
  -d, --dir             remove empty directories
  -v, --verbose         explain what is being done
      --help     display this help and exit
      --version  output version information and exit

By default, rm does not remove directories.  Use the --recursive (-r or -R)
option to remove each listed directory, too, along with all of its contents.

To remove a file whose name starts with a '-', for example '-foo',
use one of these commands:
  rm -- -foo

  rm ./-foo

Note that if you use rm to remove a file, it might be possible to recover
some of its contents, given sufficient expertise and/or time.  For greater
assurance that the contents are truly unrecoverable, consider using shred.

GNU coreutils online help: <https://www.gnu.org/software/coreutils/>
Report any translation bugs to <https://translationproject.org/team/>
Full documentation <https://www.gnu.org/software/coreutils/rm>
or available locally via: info '(coreutils) rm invocation'

💡 说明:帮助原文有三处值得划重点——其一,-I 是"超过三个文件或递归删除时提示一次",比 -i 干扰小又保留保护;其二,--preserve-root 是默认行为(do not remove '/' (default)),这就是 rm -rf / 被拒绝的来源(3.8 实测);其三,帮助末尾明确提示被删文件内容可能被专业手段恢复,要彻底销毁用 shred。

2.3 版本确认

$ rm --version | head -1
rm (GNU coreutils) 8.32

三、参数逐项实测

本章逐个参数给出「命令 + 实测回显 + 说明」,所有回显与服务器日志逐字一致;演示文件全部位于 /root/demo/rm/。

3.1 默认行为:删除单个文件

不带参数的 rm 删除文件后无任何输出。用 ls 验证结果:

$ rm /root/demo/rm/f1.txt && ls /root/demo/rm
a1.txt
a2.txt
dir1
dir2
empty3
f2.txt
g1.txt
g2.txt
p1.txt
p2.txt
p3.txt
p4.txt
q1.txt
q2.txt
q3.txt
v1.txt

f1.txt 已从列表消失。删除就是"从目录里摘掉这个名字",成功时静默——所以脚本里判断删除是否成功要靠退出码而不是输出。

3.2 -v:显示删除过程

-v(--verbose)逐条打印删除了什么,批量删除时可核对:

$ rm -v /root/demo/rm/f2.txt /root/demo/rm/a1.txt /root/demo/rm/a2.txt
removed '/root/demo/rm/f2.txt'
removed '/root/demo/rm/a1.txt'
removed '/root/demo/rm/a2.txt'

三个文件各对应一行 removed '路径'。文件名含意外字符(空格、控制符)时,-v 的输出能帮你发现"删的到底是不是想删的那个"。

3.3 -f:不存在的文件静默成功(与默认行为对照)

不带 -f 删除不存在的文件会报错、退出码 1:

$ rm /root/demo/rm/ghost.txt; echo exit=$?
rm: cannot remove '/root/demo/rm/ghost.txt': No such file or directory
exit=1

加 -f(--force)后同样的命令静默通过、退出码 0:

$ rm -f /root/demo/rm/ghost.txt; echo exit=$?
exit=0

-f 的语义(帮助原文)是 ignore nonexistent files and arguments, never prompt——文件本来就不存在也当成功。清理脚本里常配 rm -f 避免目标可能缺失导致的误报:

$ rm -f /root/demo/rm/v1.txt && ls /root/demo/rm | grep v

v1.txt 被正常删除,grep v 无输出。注意代价:-f 同时吞掉了所有报错(路径打错也不提示),高危路径上不要依赖它"兜底"。

💡 说明:-f 的"静默成功"是双刃剑——它让清理脚本免于"目标不存在就退出非零"的困扰,但也让"目录写错导致什么都没删"变得无声无息。规范用法是 rm -f 之前先用 ls 确认目标路径,或用 -v 留下删除痕迹。

3.4 -i:删除前逐个确认

-i 对每个文件都询问一次。实测删两个文件、分别回答 y 和 n:

$ printf 'y\nn\n' | rm -i /root/demo/rm/g1.txt /root/demo/rm/g2.txt; echo exit=$?
rm: remove regular empty file '/root/demo/rm/g1.txt'? rm: remove regular empty file '/root/demo/rm/g2.txt'? exit=0
$ ls /root/demo/rm | grep g
g2.txt

g1.txt 回答 y 被删除,g2.txt 回答 n 被保留,退出码 0(拒绝不视为错误)。-i 是最保守的防护,适合人工清理来源不明的目录。

3.5 -I:超过 3 个文件才提示一次

-I 是 -i 的低干扰版本:文件不超过 3 个时完全不问。实测 3 个文件静默删除:

$ rm -I /root/demo/rm/q1.txt /root/demo/rm/q2.txt /root/demo/rm/q3.txt; echo exit=$?
exit=0
$ ls /root/demo/rm | grep q

q1 到 q3 无任何提示直接删光(grep q 无输出)。凑够 4 个文件,-I 询问一次、一次性覆盖全部参数:

$ printf 'y\n' | rm -I /root/demo/rm/p1.txt /root/demo/rm/p2.txt /root/demo/rm/p3.txt /root/demo/rm/p4.txt; echo exit=$?
rm: remove 4 arguments? exit=0
$ ls /root/demo/rm | grep p
empty3

提示 remove 4 arguments? 回答 y 后 4 个文件全部删除。事后 grep p 只剩 empty3——它仍在是因为名字里恰好含字母 p,p1 到 p4 已全部删除。-I 的询问粒度是"这一次批量操作",不是逐个文件;许多发行版给 root 的别名就是 rm -I 这一档。

3.6 -r:删除目录必须递归

直接删目录会失败:

$ rm /root/demo/rm/dir1; echo exit=$?
rm: cannot remove '/root/demo/rm/dir1': Is a directory
exit=1

加 -r(--recursive)自内向外逐层删除,配合 -v 能看到完整过程:

$ rm -r -v /root/demo/rm/dir1
removed '/root/demo/rm/dir1/sub/deep.txt'
removed directory '/root/demo/rm/dir1/sub'
removed directory '/root/demo/rm/dir1'

先删最深层的文件,再删空掉的子目录,最后删顶层目录。rm -r 与通配符(如 rm -r 某目录/*)组合是事故高发区,执行前先用 ls 同参数核对要删的清单。

3.7 -d:删除空目录

-d(--dir)等价于 rmdir:只删空目录,非空即失败。空目录实测:

$ rm -d -v /root/demo/rm/empty3; echo exit=$?
removed directory '/root/demo/rm/empty3'
exit=0

非空目录实测:

$ rm -d /root/demo/rm/dir2; echo exit=$?
rm: cannot remove '/root/demo/rm/dir2': Directory not empty
exit=1

dir2 里还有 keep.txt,-d 拒绝删除并退出码 1。这个"非空即失败"的特性让 -d 比 -r 安全得多——只想清理确定的空目录时用它,绝不误伤有内容的目录。

3.8 rm -rf / 的失败保护(--preserve-root)

对根目录执行 rm -rf / 会被 rm 主动拒绝,实测回显如下(该命令只验证了拒绝机制,根目录未受任何影响):

$ rm -rf /; echo exit=$?
rm: it is dangerous to operate recursively on '/'
rm: use --no-preserve-root to override this failsafe
exit=1

这是 2.2 帮助原文中 --preserve-root(默认开启)的保护:把 / 特殊对待,递归删除直接拒绝、退出码 1。--no-preserve-root 可以关掉这层保护——生产环境永远不要使用它。同样要警惕的是绕过字面 / 的写法(如变量为空时 rm -rf "$VAR"/ 展开成 rm -rf / 的变体、在 / 下执行 rm -rf *),这类命令不受 preserve-root 保护,只能靠变量判空、绝对路径白名单等习惯来防。

四、实战示例

4.1 清理来源不明的文件:逐个确认

$ printf 'y\nn\n' | rm -i /root/demo/rm/g1.txt /root/demo/rm/g2.txt; echo exit=$?
rm: remove regular empty file '/root/demo/rm/g1.txt'? rm: remove regular empty file '/root/demo/rm/g2.txt'? exit=0
$ ls /root/demo/rm | grep g
g2.txt

逐个过目、逐个决定,回答 n 的文件原样保留(3.4 详析)。

4.2 批量清理:一次性提示防误删

$ printf 'y\n' | rm -I /root/demo/rm/p1.txt /root/demo/rm/p2.txt /root/demo/rm/p3.txt /root/demo/rm/p4.txt; echo exit=$?
rm: remove 4 arguments? exit=0
$ ls /root/demo/rm | grep p
empty3

-I 只打断一次,确认的是整批操作(3.5 详析)。大批量清理建议先 ls 预览同参数的匹配清单,再原样替换成 rm。

4.3 脚本静默清理:目标可能不存在

$ rm -f /root/demo/rm/ghost.txt; echo exit=$?
exit=0
$ rm -f /root/demo/rm/v1.txt && ls /root/demo/rm | grep v

目标存在则删除、不存在也返回 0,清理脚本不会因目标缺失而中断(3.3 详析)。

五、注意事项与常见问题

Q1:rm 删掉的数据还能恢复吗? rm 只是把文件名从目录里摘除并释放 inode 引用,数据块本身可能还在磁盘上,帮助原文明确提示"可能被专业手段恢复";要彻底销毁用 shred 覆写后删除(见 2.2 帮助原文说明)。

Q2:为什么加了 -f 之后删错路径也不报错? -f 的设计就是 ignore nonexistent files and arguments, never prompt,连同一切报错一起静默。清理脚本可用,但高危路径上应先 ls 核对再删。

Q3:-i 和 -I 到底怎么选? 逐个确认选 -i;批量操作选 -I(超过 3 个文件或递归删除时提示一次)。日常交互推荐至少 -I,见 3.4 与 3.5 的实测对比。

Q4:为什么 rm 删目录报 Is a directory? rm 默认只删文件,目录必须加 -r 递归删除(见 3.6);只删空目录可用更安全的 -d(见 3.7)。

Q5:rm -d 和 rmdir 一样吗? 语义一致:只删空目录、非空即失败。rm -d 的好处是与 rm 其他参数(-v)同源,脚本里风格统一(见 3.7 两个实测)。

Q6:rm -rf / 为什么被拒绝?拒绝能关吗? 默认的 --preserve-root 把 / 特殊对待、递归删除直接拒绝(见 3.8 实测)。可以用 --no-preserve-root 关闭,但生产环境永远不要用;真正要做的是避免变量为空、路径拼写这类让命令"意外指向根"的情形。

Q7:rm 失败时退出码是多少? 失败为 1(如路径不存在、目录未递归、根目录保护拒绝),全部成功为 0;-i/-I 回答 n 拒绝删除不算失败,仍是 0(见 3.3、3.4、3.5、3.8 的 exit 实测)。

Q8:怎么防止误删? 组合拳:交互会话设别名 rm -I;脚本用 rm -f 前先 ls 同参数预览;删除变量拼接的路径前判空;能确定"非空不删"的场景用 rm -d;重要数据先备份再删。

六、参考链接