你维护一个项目目录,里面混杂了源代码、日志、临时文件和编译产物。你想一次性清理掉所有无用文件,只保留几个核心文件——但手动一个个排除太慢,用 rm -rf * 又会误删重要内容。
有没有办法“反向删除”:删除所有文件,除了我指定的那几个?
答案是肯定的。本文将带你掌握 4 种高阶删除技巧,覆盖各种“排除删除”场景。
一、场景引入:什么时候需要“反向删除”?
| | |
|---|
| 保留main.py、config.yaml,删除其他所有文件 | |
| | |
| | |
| | |
掌握以下 4 种方法,你可以精准控制“删除什么”和“不删除什么”。
二、方法一:shopt -s extglob + !(pattern) 扩展匹配(最常用)
Bash 的 extglob(扩展通配符)提供了反向匹配能力,这是“删除除指定文件外所有文件”最直接的方法。
启用 extglob
shopt -s extglob
基础语法
| | |
|---|
| | !(*.log) 匹配所有不以 .log 结尾的文件 |
| | |
| | |
| | |
| | |
实战示例
删除当前目录下所有文件,但保留 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)
⚠️ 重要注意事项
| | |
|---|
| 在脚本中直接使用!(pattern) 会报语法错误 | |
| | 需要配合dotglob:shopt -s dotglob |
| rm -rf !(src) 会删除src 目录本身吗? | !(src) 排除 src 目录本身,但不会排除其子内容 |
| | |
启用 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 的优势
四、方法三:使用 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 "{}"
⚠️ 注意事项
六、四种方法对比
🏆 推荐首选: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 {} \;
八、常见坑与避坑指南
| | |
|---|
| | |
| find . ! -name "src" -delete 递归删除 src 内的文件 | |
| ❌ 用rm -rf 配合 find 删除目录时忘记排除自身 | find . -maxdepth 1 ! -name "src" -delete 会删除. 目录本身 | 用-maxdepth 1 限制层级,或用 -mindepth 1 |
| | |
| ❌ 在rm -rf !(pattern) 中忘记加引号 | | |
脚本中安全使用 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 种方法任选:
| | |
|---|
| | shopt -s extglob; rm -rf !(main.py |
| | find . -maxdepth 1 ! -name "main.py" -delete |
| | find . -type f -size +1M ! -name "*.iso" -delete |
| | rsync -av --delete --exclude="keep/" empty/ target/ |
核心安全原则:
- 删除前务必先用
ls 或 find -print 预览匹配的文件列表。 - 在脚本中使用
set -o noclobber 或交互确认(read -p)。 - 考虑使用
trash-cli 作为删除的“保险丝”。
掌握这些高阶技巧后,你不仅能精准控制删除范围,还能有效避免误删事故。用好了,它们是效率工具;用不好,它们是“炸弹”。
如果你觉得本文对你有帮助,欢迎点赞、推荐、转发,关注我,后续会分享更多Linux入门干货!
文 / 零距技术仓
记录每一次真实的折腾 (#^.^#)
🚀 想看到更多实用折腾技巧?
👉 先关注
💬 评论区说说你的经历或想看的内容
👍 点赞表示支持
🔁 顺手分享给也在折腾的人,让大家都少踩坑 😎