Bash读取含通配符字符串的异常行为及解决方法问询
这是个典型的bash路径名扩展(globbing)导致的问题,我来一步步帮你理清并解决:
问题根源
bash默认会对未加引号的变量做两件事:单词拆分和路径名扩展(也就是把*这类通配符替换成匹配的文件名)。你看到echo index name: $index_name输出展开后的文件名,本质是没给$index_name加双引号,触发了通配符扩展——但实际上index_name变量存储的还是原始的INDEX*字符串,只是输出时被bash自动展开了。
解决方法
1. 保留原始通配符字符串,避免意外扩展
无论读取变量还是输出变量,都用双引号包围,让bash把它当成普通字符串处理:
# 读取tmp文件内容,双引号确保原始字符串完整保留 index_name="$(<tmp)" # 输出时加双引号,彻底避免通配符扩展 echo "index name: $index_name"
这样输出结果就会是index name: INDEX*,和tmp文件里的内容一致。
2. 生成匹配通配符的文件名数组
如果你需要把所有以该索引名开头的文件(比如INDEX*.file1、INDEX*.file2)拆分成独立的数组元素,不用手动拆分字符串,直接利用bash的通配符扩展生成数组更可靠:
# 先确保拿到原始的索引名字符串 index_name="$(<tmp)" # 可选:开启nullglob选项——如果没有匹配的文件,数组会为空,而不是保留通配符字符串 shopt -s nullglob # 生成匹配的文件名数组,bash会自动扩展通配符 file_array=("$index_name".*) # 用完可以关闭nullglob shopt -u nullglob # 验证数组元素 echo "匹配到的文件:" for file in "${file_array[@]}"; do echo "- $file" done
这样file_array里的每个元素就是一个独立的文件名,完全符合你后续用curl单独发送的需求。
为什么你之前的数组拆分失败?
你用IFS=' ' read -a index_array <<< "$index_name"得到单个元素,是因为index_name的实际值是INDEX*(一个没有空格的完整字符串),所以read只会把它当成一个元素。而你看到的INDEX*.file1 INDEX*.file2是未加引号的变量展开后的临时结果,并不是index_name存储的真实值。
额外提示
如果担心通配符的安全问题(比如tmp文件内容不可控),可以用printf %q转义特殊字符,但在你的场景里,tmp文件是自己脚本生成的,内容可控,直接用双引号和通配符扩展就足够安全。
内容的提问来源于stack exchange,提问作者mizenetofa1989

