当前位置:首页>Linux>Linux删除高阶技巧:如何删除“除指定文件外”的所有文件?

Linux删除高阶技巧:如何删除“除指定文件外”的所有文件?

  • 2026-10-11 07:04:52
Linux删除高阶技巧:如何删除“除指定文件外”的所有文件?

你维护一个项目目录,里面混杂了源代码、日志、临时文件和编译产物。你想一次性清理掉所有无用文件,只保留几个核心文件——但手动一个个排除太慢,用 rm -rf * 又会误删重要内容。
有没有办法“反向删除”:删除所有文件,除了我指定的那几个?
答案是肯定的。本文将带你掌握 4 种高阶删除技巧,覆盖各种“排除删除”场景。


一、场景引入:什么时候需要“反向删除”?

场景
需求
传统做法的问题
清理项目目录
保留main.py、config.yaml,删除其他所有文件
手动删太慢,容易误删
清理日志目录
保留最近 3 天的日志,删除更早的
rm * 会删掉所有
清理下载文件夹
保留.iso 文件,删除其他格式
通配符很难反向匹配
清理备份目录
保留最新的 5 个备份,删除其余
需要按时间筛选排除

掌握以下 4 种方法,你可以精准控制“删除什么”和“不删除什么”。


二、方法一:shopt -s extglob + !(pattern) 扩展匹配(最常用)

Bash 的 extglob(扩展通配符)提供了反向匹配能力,这是“删除除指定文件外所有文件”最直接的方法。

启用 extglob

shopt -s extglob

基础语法

模式
含义
示例
!(pattern)
排除匹配 pattern 的内容
!(*.log) 匹配所有不以 .log 结尾的文件
*(pattern)
匹配 0 次或多次
较少用于删除场景
?(pattern)
匹配 0 次或 1 次
较少用于删除场景
+(pattern)
匹配 1 次或多次
较少用于删除场景
@(pattern)
匹配其中一种
@(*.jpg)

实战示例

删除当前目录下所有文件,但保留 main.py 和 config.yaml

如果你之前在  ~/.bashrc 中将rm改为了mv(alias rm='mv -t ~/.trash')

请移除(如果移除还是替rm是移动,那么命令行执行:unalias rm )

shopt -s extglob
rm -rf !(main.py|config.yaml)

删除所有文件,但保留所有 .txt 和 .md 文件

shopt -s extglob
rm -rf !(*.txt|*.md)

删除所有文件,但保留目录 src/ 和 lib/

shopt -s extglob
rm -rf !(src|lib)

⚠️ 重要注意事项

坑点
说明
解决方案
extglob 默认未启用
在脚本中直接使用!(pattern) 会报语法错误
脚本开头加上shopt -s extglob
通配符不匹配隐藏文件
!(pattern) 默认不匹配以. 开头的文件
需要配合dotglob:shopt -s dotglob
递归删除时排除目录内容
rm -rf !(src) 会删除src 目录本身吗?
!(src) 排除 src 目录本身,但不会排除其子内容
路径包含空格或特殊字符
rm -rf !(my file) 会出错
用find 方法代替(见下文)

启用 dotglob(匹配隐藏文件)

shopt -s dotglob extglob
rm -rf !(.git|.env)    # 删除所有,但保留 .git 和 .env

三、方法二:find 命令的 -not / ! 排除(最灵活)

find 命令是 Linux 文件操作的瑞士军刀,配合 -not 或 ! 可以精确排除文件。

语法

find 路径 -条件 -not -name "排除模式" -exec rm -rf {} \;
# 或使用 ! 
find 路径 -条件 ! -name "排除模式" -exec rm -rf {} \;

实战示例

删除当前目录所有文件,但保留 main.py

find . -maxdepth 1 -type f ! -name "main.py" -exec rm -f {} \;

删除所有文件,但保留多个指定文件

find . -maxdepth 1 -type f ! \( -name "main.py" -o -name "config.yaml" \) -exec rm -f {} \;

删除所有文件,但保留整个 src/ 目录

find . -maxdepth 1 ! -name "src" -exec rm -rf {} \;

💡 注意:-maxdepth 1 限制只处理当前目录,不递归进入子目录。

删除 7 天前的日志,但保留 error.log 和 access.log

find /var/log/ -name "*.log" -mtime +7 ! -name "error.log" ! -name "access.log" -exec rm -f {} \;

先预览再删除(安全习惯)

# 先列出会删除的文件
find . -maxdepth 1 -type f ! -name "main.py" -print

# 确认无误后再删除
find . -maxdepth 1 -type f ! -name "main.py" -delete

-delete 是 GNU find 的扩展,比 -exec rm 更高效。

find 的优势

  • 支持复杂的条件组合(文件名、大小、时间、权限等)
  • 自动处理文件名中的空格和特殊字符
  • 可以在删除前 -print 预览

四、方法三:使用 rsync 反向同步(备份场景)

rsync 通常用于同步文件,但也可以用来“删除除指定文件外的所有文件”——通过同步一个空目录,并排除需要保留的文件。

原理

先创建一个空目录,然后用 rsync 将空目录同步到目标目录,排除掉需要保留的文件,未排除的文件会被删除。

实战示例

mkdir /tmp/empty
rsync -av --delete --exclude="main.py" --exclude="config.yaml" /tmp/empty/ /target/dir/
rmdir /tmp/empty

⚠️ 这种方法比较迂回,不推荐日常使用,但在备份场景中很有用(例如:同步时排除某些文件)。


五、方法四:ls + grep + xargs 组合(按条件筛选)

当排除条件非常复杂时,可以用 ls + grep + xargs 组合。

实战示例

删除当前目录所有文件,但保留 .txt 和 .md 之外的文件

ls -1 | grep -v -E "\.(txt|md)$" | xargs rm -f

删除当前目录所有文件,但保留 main.py 和 config.yaml

ls -1 | grep -v -E "^(main.py|config.yaml)$" | xargs rm -f

处理文件名中的空格

ls -1 | grep -v -E "^(main.py|config.yaml)$" | xargs -I {} rm -f "{}"

⚠️ 注意事项

  • ls
     输出在文件名包含换行符时可能出错(极少见)
  • 不匹配隐藏文件(默认不显示)
  • 适合快速一次性操作,不适合脚本

六、四种方法对比

方法
难度
灵活性
处理特殊文件名
适用场景
extglob 通配符
低
中
需引号处理
快速交互式删除
find
中
高
✅ 自动处理
最推荐,最灵活
rsync
高
中
✅
备份同步场景
ls + grep + xargs
低
中
❌ 需额外处理
快速一次性操作

🏆 推荐首选:find 方法兼顾安全性和灵活性。


七、完整实操案例:清理项目目录

假设你的项目目录 /home/alice/myproject/ 内容如下:

myproject/
├── .git/
├── .env
├── main.py
├── config.yaml
├── test.py
├── __pycache__/
├── logs/
│   ├── error.log
│   └── debug.log
├── tmp/
└── README.md

目标:删除所有文件,但保留 main.py、config.yaml、.git/ 目录。

使用 extglob 方法

cd /home/alice/myproject
shopt -s extglob dotglob
rm -rf !(main.py|config.yaml|.git)

结果:README.md、test.py、__pycache__/、logs/、tmp/ 全部删除。

使用 find 方法(更安全)

cd /home/alice/myproject
# 先预览
find . -maxdepth 1 ! -name "main.py" ! -name "config.yaml" ! -name ".git" -print

# 确认后删除
find . -maxdepth 1 ! -name "main.py" ! -name "config.yaml" ! -name ".git" -exec rm -rf {} \;

八、常见坑与避坑指南

坑点
错误做法
正确做法
❌ 在脚本中使用extglob 但未启用
脚本中直接写rm -rf !(file)
在脚本开头添加shopt -s extglob
❌ 忘记-maxdepth 导致递归删除
find . ! -name "src" -delete 递归删除 src 内的文件
加上-maxdepth 1 或 -prune
❌ 用rm -rf 配合 find 删除目录时忘记排除自身
find . -maxdepth 1 ! -name "src" -delete 会删除. 目录本身
用-maxdepth 1 限制层级,或用 -mindepth 1
❌ 删除前不预览
直接执行删除命令
先用-print 或 echo 预览
❌ 在rm -rf !(pattern) 中忘记加引号
rm -rf !(my file) 报错
使用 find 方法避免此类问题

脚本中安全使用 extglob 的示例

#!/bin/bash
# 启用 extglob 和 dotglob
shopt -s extglob dotglob

# 定义要保留的文件/目录
KEEP="main.py|config.yaml|.git"

# 切换目录
cd /path/to/project || exit 1

# 预览将要删除的内容
echo"将要删除以下文件/目录:"
ls -d !($KEEP) 2>/dev/null || echo"(无匹配项)"

# 确认后执行删除
read -p "确认删除以上内容?(y/N) " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
    rm -rf !($KEEP)
echo"删除完成。"
else
echo"已取消。"
fi

九、总结

删除除指定文件外的所有文件,4 种方法任选:

场景
推荐方法
命令示例
交互式快速删除
extglob
shopt -s extglob; rm -rf !(main.py
脚本中安全删除
find
find . -maxdepth 1 ! -name "main.py" -delete
按条件复杂筛选
find
find . -type f -size +1M ! -name "*.iso" -delete
备份同步场景
rsync
rsync -av --delete --exclude="keep/" empty/ target/

核心安全原则:

  1. 删除前务必先用 ls 或 find -print 预览匹配的文件列表。
  2. 在脚本中使用 set -o noclobber 或交互确认(read -p)。
  3. 考虑使用 trash-cli 作为删除的“保险丝”。
  4. 始终问自己一句:“如果删错了,我能恢复吗?”

掌握这些高阶技巧后,你不仅能精准控制删除范围,还能有效避免误删事故。用好了,它们是效率工具;用不好,它们是“炸弹”。

如果你觉得本文对你有帮助,欢迎点赞、推荐、转发,关注我,后续会分享更多Linux入门干货!

文 / 零距技术仓
记录每一次真实的折腾 (#^.^#)

🚀 想看到更多实用折腾技巧?
👉 先关注
💬 评论区说说你的经历或想看的内容
👍 点赞表示支持
🔁 顺手分享给也在折腾的人,让大家都少踩坑 😎

最新文章

随机文章