zsh中rm !(例外文件)与bash表现差异的原因及修复方法
zsh执行
rm -rf !(no)报错的原因及解决办法 测试场景复现
首先在zsh中创建测试文件与目录:
➜ Downloads touch abc.txt 1 2 3 4321 4 9; mkdir a b c no ➜ Downloads ls 1 2 3 4 4321 9 a abc.txt b c no
尝试在zsh中删除除no外的所有内容,触发错误:
➜ Downloads rm -rf -v !(no) zsh: unknown sort specifier
切换到bash执行相同命令则正常完成删除:
➜ Downloads bash vladyslav@kdeneonlinux:~/Downloads$ rm -rf -v !(no) removed '1' removed '2' removed '3' removed '4' removed '4321' removed '9' removed directory 'a' removed 'abc.txt' removed directory 'b' removed directory 'c' vladyslav@kdeneonlinux:~/Downloads$ ls no vladyslav@kdeneonlinux:~/Downloads$ exit exit ➜ Downloads ls no
报错原因
zsh与bash的通配符扩展规则存在差异:
- 在bash中,
!(pattern)属于**扩展通配符(extglob)**语法,用于匹配除指定模式外的所有文件/目录。 - 默认配置的zsh中,
!(...)会被解析为历史扩展语法,zsh将其识别为历史命令的排序修饰符,而no并非合法的排序符,因此抛出“unknown sort specifier”错误。
解决办法
方法1:启用zsh的扩展通配符功能
zsh支持类似bash的extglob语法,只需先启用extended_glob选项:
- 临时启用(当前会话有效):
之后即可执行和bash相同的命令:setopt extended_glob
也可以用zsh更常用的否定匹配写法:rm -rf -v !(no)rm -rf -v ^no - 永久启用(所有zsh会话生效):
将setopt extended_glob添加到~/.zshrc文件末尾,保存后执行source ~/.zshrc使配置立即生效。
方法2:使用zsh原生匹配语法
无需启用扩展选项,直接用zsh的原生通配符匹配:
rm -rf -v *(^no)
如果需要包含隐藏文件,可改用:
rm -rf -v .*(^no)
方法3:跨shell通用的find命令
如果需要在zsh和bash中通用,推荐使用find命令:
find . -maxdepth 1 ! -name '.' ! -name 'no' -exec rm -rfv {} +
-maxdepth 1确保只处理当前目录下的内容,不会递归进入子目录;! -name '.'避免误删当前目录本身。
内容的提问来源于stack exchange,提问作者Vladyslav Rehan
相关产品推荐
相关产品推荐

