如何用Glob取反规则编写mv命令移动不含指定字符串的文件并排除指定目录
命令失效的核心原因
所有之前尝试的命令未达到预期,本质是扩展通配符的模式逻辑偏差、语法结构不规范,加上部分shell环境默认未启用对应扩展,导致排除规则完全没有生效:
mv *!(Copy)* ..:启用extglob时,*!(Copy)*的匹配逻辑是「任意开头 + 一段不等于Copy的字符片段 + 任意结尾」,几乎所有文件名都会命中该规则——哪怕是fileCopy.txt,也会因为前面的file、后面的.txt都是非Copy片段被匹配,最终导致全量文件被移动mv !(Copy) ..:仅能排除「文件名精确等于Copy」的条目,完全没有覆盖「文件名任意位置包含Copy字符串」的场景,所有带Copy的文件都会被纳入移动范围mv !((*Copy*)|(directory)) ..:括号嵌套结构不符合extglob语法规范,多套的括号会直接触发语法报错mv (*!(Copy)*|!(directory)) ..:模式开头缺少取反标记,匹配逻辑完全反向,最终命中目录下的所有内容mv !(Copy|directory) ..:仅排除「精确命名为Copy」和「精确命名为directory」的条目,未将文件名内嵌Copy的长文件名纳入排除范围,导致带Copy的文件全部被移动
正确实现方案
方案1:bash原生extglob写法
这类!()形式的排除语法,需要先在当前shell会话启用extglob扩展才能生效:shopt -s extglob
执行正式移动命令:mv !(*Copy*|directory) ..
该命令的匹配逻辑为:排除两类内容——所有文件名任意位置包含Copy的条目、名为directory的目录,剩余所有条目(普通文件、其他子目录)全部移动到上级目录。
操作提示:首次使用建议先将
mv替换为echo,打印所有将被匹配的条目,确认规则符合预期后再执行正式移动,避免误操作。
方案2:find命令写法(无shell配置依赖)
这种方法不需要提前修改shell扩展配置,兼容性更强,执行前可先预览所有匹配结果:find . -maxdepth 1 -mindepth 1 ! -name '*Copy*' ! -name 'directory'
确认输出列表中没有带Copy的文件、也没有包含directory目录后,再执行正式移动:find . -maxdepth 1 -mindepth 1 ! -name '*Copy*' ! -name 'directory' -exec mv {} ../ \;
各参数作用:
-maxdepth 1:仅遍历当前目录第一层的内容,不递归进入子目录查找-mindepth 1:排除当前目录本身的路径! -name '*Copy*':过滤所有文件名包含Copy的条目! -name 'directory':过滤名为directory的条目
内容的提问来源于stack exchange,提问作者maximilian2000
相关产品推荐
相关产品推荐

