如何通过遍历数组生成find命令的-iname参数?
Bash脚本中通过循环生成find命令的-iname参数问题
需求与问题
需要编写Bash脚本,通过循环将多个文件后缀名作为-iname参数传递给find命令,最终生成的目标命令为:
find -L $destDir \( -iname "*.mp4" -or -iname "*.AVI" -or -iname "*.MTS" \)
但当前编写的脚本无法正常运行,原脚本如下:
#!/bin/bash destDir= '/share/Multimedia2/VideoLink/tmp' v_end=("mp4" "AVI" "MTS"); arr_len=${#v_end[@]}; arr_len=(($arr_len--)) find -L $destDir \(( for ( i=0; i<$arr_len; i++); do ( -iname "${v_end[$i]} -or" ) done ) -iname "${v_end[$arr_len]}" \)
原脚本的错误点
- 变量赋值错误:
destDir= '/share/...'中等号后不能有空格,正确写法为destDir='/share/Multimedia2/VideoLink/tmp' - 数组长度计算错误:
arr_len=(($arr_len--))语法无效,Bash中整数运算应使用arr_len=$((arr_len - 1)),且原逻辑未正确对应数组索引 - 循环语法错误:Bash的C-style循环写法应为
for ((i=0; i<arr_len; i++)),而非for ( i=0; i<$arr_len; i++); - 命令内嵌循环错误:无法直接在
find命令中嵌入for循环结构,Bash不会自动解析这种嵌套代码
正确解决方案
方案1:构建参数数组(推荐,健壮性高)
通过数组逐步构建find的条件参数,避免空格、特殊字符等问题:
#!/bin/bash destDir='/share/Multimedia2/VideoLink/tmp' v_end=("mp4" "AVI" "MTS") # 初始化存储find条件的数组 find_conditions=() # 先逐个生成-iname参数 for ext in "${v_end[@]}"; do find_conditions+=(-iname "*.$ext") done # 将参数用-or连接成完整条件 if [ ${#find_conditions[@]} -gt 0 ]; then final_condition=("${find_conditions[0]}") # 从第二个参数开始,依次添加-or和对应条件 for cond in "${find_conditions[@]:1}"; do final_condition+=(-or "$cond") done # 执行find命令 find -L "$destDir" \( "${final_condition[@]}" \) fi
方案2:用printf快速生成参数(简洁写法)
通过printf格式化输出条件字符串,再移除末尾多余的-or:
#!/bin/bash destDir='/share/Multimedia2/VideoLink/tmp' v_end=("mp4" "AVI" "MTS") # 生成带-or的条件字符串 condition_str=$(printf -- '-iname "*.%s" -or ' "${v_end[@]}") # 移除最后一个多余的 -or condition_str=${condition_str% -or } # 执行find命令 find -L "$destDir" \( $condition_str \)
注意事项
- 始终用双引号包裹变量和数组元素,避免路径或文件名含空格时出现参数拆分错误
find命令中的括号需要用反斜杠转义,确保Shell将其传递给find而非自行解析- 参数数组方案更适合处理含特殊字符的场景,健壮性更强
内容的提问来源于stack exchange,提问作者Donaufisch
相关产品推荐
相关产品推荐

