如何在find命令中使用变量结合循环实现多文件名排除
动态构造find多文件名排除参数实现方案
问题描述
需要配置大量文件名排除规则时,手动逐行写! -name参数维护成本高,希望通过循环方式自动生成find的匹配参数,但变量引用、参数拼接过程中容易出现语法错误。
初始测试代码如下:
tabSearch=("20220514*" "20220508*" "20220515*") find . \( ! -name "${tabSearch[0]}" -a ! -name "${tabSearch[1]}" \)
目标效果:根据排除规则数组的实际长度,自动生成对应数量的排除匹配参数,适配任意数量的排除规则,无需手动修改find命令主体。
推荐实现方式
数组构造法(兼容性最好,无转义问题)
利用bash数组存储动态生成的参数,遍历排除规则数组逐个追加参数,最后一次性展开传给find,完全避免字符串拼接带来的转义、拆分问题:
#!/bin/bash # 定义所有需要排除的文件名通配规则 tabSearch=("20220514*" "20220508*" "20220515*") # 初始化find参数存储数组 find_exclude_args=() for rule in "${tabSearch[@]}"; do find_exclude_args+=(! -name "$rule") done # 执行find命令,括号对所有排除规则做逻辑分组 find . \( "${find_exclude_args[@]}" \)
关键注意事项:
- 数组展开时必须用双引号包裹
"${find_exclude_args[@]}",否则包含空格、特殊通配符的规则会被shell错误拆分,导致匹配逻辑失效。 - 逻辑分组用的转义括号
\(、\)和相邻参数之间必须保留空格,否则find会将括号与相邻参数识别为同一个匹配值,抛出语法错误。 - 连续的匹配规则之间find默认按逻辑与(
-a)处理,不需要手动在规则之间追加-a参数。
正则匹配法(适合规则格式统一的场景)
如果所有排除规则的格式统一,不需要循环构造参数,直接用find的正则匹配能力一次性写排除规则即可,注意需要指定兼容的正则类型:
# 排除所有以20220514、20220508、20220515开头的文件/目录 find . -regextype posix-extended ! -regex '.*/(20220514|20220508|20220515)[^/]*$'
原有写法的问题
原写法手动通过数组索引指定排除规则,扩展性极差:当排除规则数量变化时,必须手动增删! -name "${tabSearch[x]}"片段,一旦数组长度和硬编码的索引不匹配,就会出现漏排除、空参数的语法错误。
内容的提问来源于stack exchange,提问作者Aurélien-Fr
相关产品推荐
相关产品推荐

