
当你在终端里清理旧日志、构建产物或临时文件时,通常第一个想到的命令就是 rm。它从文件系统中删除文件和目录,而且是永久删除,并不会把文件送进桌面的回收站文件夹。
本指南通过实用示例讲解如何在 Linux 中使用 rm 命令,包括递归删除目录、确认提示、通配符匹配,以及更安全地使用 rm -rf 的方法。
rm 命令语法
rm 命令的通用语法如下:
rm [OPTIONS] FILE...
默认情况下,rm 不会删除目录,并且在删除文件之前不会提示确认。
常用 rm 选项
最常用的 rm 选项用于控制递归、提示和输出:
- -f, --force — 忽略不存在的文件,且从不提示确认。
- -i — 每次删除前都提示确认。
- -I — 在删除超过三个文件、或执行递归删除之前,只提示一次。
- -r, -R, --recursive — 递归删除目录及其内容。
- -d, --dir — 删除空目录。
- -v, --verbose — 在删除发生时打印每个被移除的条目。
- --interactive=WHEN — 将提示行为设为 never(从不)、once(一次)或 always(总是)。
- --one-file-system — 递归删除时,跳过位于不同文件系统中的目录。
- --preserve-root — 拒绝删除 /,这是 GNU rm 的默认保护。
你可以组合使用短选项。例如,rm -rv dirname 会递归删除一个目录,并打印每一个被移除的路径。
删除单个文件
要删除单个文件,把文件名作为参数传入即可:
rm filename
如果文件没有写保护,rm 会静默删除它,不输出任何内容。删除成功时,rm 返回退出码 0。
如果你对父目录没有写和执行权限,rm 会失败并报「Permission denied(权限被拒绝)」错误。「Operation not permitted(操作不被允许)」则指向另一种原因:要么父目录设置了 sticky 位且该文件属于其他用户(/tmp 正是靠这种方式保护自己的内容),要么该文件是不可变的(immutable)。
当删除一个写保护文件时,rm 会提示确认:
rm: remove write-protected regular empty file 'filename'?
输入 y 并按回车确认。
要跳过提示、不经确认直接删除文件,使用 -f(force,强制)选项:
rm -f filename
-f 还会静默忽略不存在的文件,而不是返回错误。
要看到每个文件被删除的过程,使用 -v(verbose,详细)选项:
rm -v filename
removed 'filename'
详细输出在一条命令匹配了多个文件、而你想记录究竟删除了什么时非常有用。
删除多个文件
与 unlink 命令不同,rm 可以一次接受多个文件名:
rm filename1 filename2 filename3
你也可以使用 shell 的通配符来匹配多个文件。例如,要删除当前目录下所有 .png 文件:
rm *.png
在运行带通配符的 rm 之前,先用 ls 预览一下会匹配到哪些文件:
ls *.png
shell 会在 rm 运行之前展开 *.png。如果通配模式匹配到的文件比预期多,在真正删除任何东西之前先调整模式。
删除目录
要删除一个或多个空目录,使用 -d 选项:
rm -d dirname
rm -d 在功能上等同于 rmdir 命令。
要递归删除一个非空目录及其全部内容,使用 -r(recursive,递归)选项:
rm -r dirname
这会删除该目录及其内部的一切,包括文件、子目录和符号链接。
删除前确认提示
-i 选项会在删除每个文件之前提示确认:
rm -i filename1 filename2
rm: remove regular empty file 'filename1'? rm: remove regular empty file 'filename2'?
输入 y 并按回车逐个确认每个文件。
当删除超过三个文件、或递归删除一个目录时,使用 -I(大写)选项,针对整个操作只给一次提示,而不是每个文件一次:
rm -I filename1 filename2 filename3 filename4
rm: remove 4 arguments?
rm -rf
组合 -r 和 -f 会删除一个目录及其全部内容,且全程不提示,即便目录内的文件是写保护的也不例外:
rm -rf dirname
短选项的先后顺序无关紧要,所以 rm -fr dirname 与 rm -rf dirname 效果完全相同。
在使用脚本中的变量时,先打印目标路径确认,或先用 ls 测试一下。这有助于在变量为空或取值异常时,赶在它们被传给 rm -rf 之前发现问题。
删除以短横线开头的文件
以 - 开头的文件名会被 rm 当作选项来解析。要删除这类文件,用 -- 表示选项的结束:
rm -- -filename
另一种方式是在路径前加上 ./ :
rm ./-filename
速查表
要获取一份可打印的速查表,请参阅 rm 备忘单。
| 任务 | 命令 |
|---|---|
| 删除一个文件 | rm file |
| 删除且不提示 | rm -f file |
| 显示详细输出 | rm -v file |
| 删除多个文件 | rm file1 file2 file3 |
| 按通配符删除 | rm *.log |
| 删除空目录 | rm -d dir |
| 递归删除目录 | rm -r dir |
| 递归删除且不提示 | rm -rf dir |
| 递归并显示详细 | rm -rv dir |
| 删除每个文件前提示 | rm -i file |
| 删除多个文件只提示一次 | rm -I file1 file2 ... |
| 删除以 - 开头的文件 | rm -- -filename |
| 按名称控制提示行为 | rm --interactive=once file1 file2 |
故障排查
「操作不被允许(Operation not permitted)」:父目录设置了 sticky 位,且该文件属于另一个用户——这正是 /tmp 阻止一个用户删除其他用户文件的方式;或者该文件是不可变的。用 ls -ld dirname 检查目录,用 lsattr filename 检查文件,只有在确实需要 root 权限时才使用 sudo。
「权限被拒绝(Permission denied)」:父目录的权限通常决定了你能否删除其中的条目。用 ls -ld dirname 检查目录,再视情况用 chmod 调整权限或用 chown 调整归属。
「cannot remove 'dirname': Is a directory(无法删除 'dirname':是一个目录)」:rm 需要 -r 标志才能删除目录。请改用 rm -r dirname。
「cannot remove 'file': No such file or directory(无法删除 'file':没有那个文件或目录)」:文件不存在或路径不正确。用 ls 核实路径。要在脚本中抑制这个错误,使用 rm -f。
「写保护文件未被删除」:没有 -f 时,rm 会在删除写保护文件前提示。要么输入 y 确认,要么用 rm -f 跳过提示。
「不可变文件无法删除」:在支持文件属性的 Linux 文件系统上,不可变文件即使 root 也无法删除,直到清除该属性。用 lsattr filename 检查,只有在确定该文件确实应该删除时,才用 sudo chattr -i filename 移除不可变标志。
「设备或资源忙(Device or resource busy)」:该路径可能是挂载点,或有进程正在使用这个目录。在重试之前,先用 findmnt 检查已挂载的文件系统,用 lsof +D dirname 查看该路径的活跃使用者。
常见问题(FAQ)
用 rm 删除的文件能恢复吗?不容易。rm 会立即移除文件系统条目,而不会把文件移到回收站文件夹。在 ext4 上可以借助 extundelete 或 testdisk 等工具尝试恢复,但能否成功取决于磁盘块是否已被覆盖。更安全的做法是使用 trash-cli 这类回收站工具(trash file 会把文件移到 ~/.local/share/Trash)。
rm 和 unlink 有什么区别?unlink 通过直接调用 unlink 系统调用来删除单个文件。rm 是更高层的工具,支持多文件、目录、通配符和交互式提示。
如何删除一个目录里的所有文件,但保留目录本身?用 rm -rf dirname/* 删除非隐藏内容,同时保留目录本身。像 * 这样的 shell 通配符默认不匹配隐藏的点文件。要在不删除父目录的前提下清除隐藏和非隐藏内容,先核实路径,再用 find dirname -mindepth 1 -delete。
rm -rf / 危险吗?是的。它会尝试删除文件系统中的一切。现代 Linux 系统默认通过 --preserve-root 保护机制拦截它,但像 rm -rf /* 这样的变体、或显式指定挂载的根路径,并不总是受保护。永远不要运行这条命令。
如何删除超过 N 天的文件?使用 find 命令:find /path -type f -mtime +30 -delete 会删除最近 30 天内未被修改的文件。
总结
在执行任何 rm -rf 之前,先用 ls 对同样的路径跑一遍,尤其是涉及变量时。对于频繁清理构建产物或日志的场景,可以把 rm 别名设为 trash-cli 的 trash 命令,这样误删也能恢复。