You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Shell脚本中无法使用{范围}语法匹配文件名的问题

解决Shell脚本中变量拼接大括号范围失效的问题

问题场景

要写Shell脚本统计指定分钟范围内的日志文件数量,文件名格式是SOMEFILES_20230922<分钟数>.log,比如想匹配30到35分钟的文件,直接在命令行敲ls -lrth /path/to/my/directory/SOMEFILES_20230922{30..35}.log | wc -l能正常出结果,但放到脚本里用变量拼接范围就不行,总是提示文件不存在。

用户的示例脚本(注意里面变量名有笔误,MinInicial应该是InicialMin):

InicialMin=$(date -d "-5 minutes" +%M)
FinalMin=$(date +%M)
MinRange="${MinInicial}..${MinFinal}" # 正确写法应该是${InicialMin}..${FinalMin},输出示例:30..35

Results=$(ls -lrth /path/to/my/directory/SOMEFILES_20230922{$MinRange}.log | wc -l)
echo "Files found: ${Results}"

试过这些写法都没用:

Results=$(ls -lrth /path/to/my/directory/SOMEFILES_20230922\{$MinRange\}.log | wc -l)
Results=$(ls -lrth /path/to/my/directory/SOMEFILES_20230922'{'$MinRange'}'.log | wc -l)
Results=$(ls -lrth /path/to/my/directory/SOMEFILES_20230922{{$MinRange}}.log | wc -l)

问题原因

Shell的大括号扩展是在变量展开之前执行的。也就是说,当脚本执行到{$MinRange}时,Shell先处理大括号,这时候MinRange还没被替换成30..35,会被当成字面量{MinRange},最终生成的路径是SOMEFILES_20230922{30..35}.log——这里的{30..35}会被当成文件名的一部分,自然找不到对应文件。

解决方案

方法1:用eval强制二次解析

eval可以让Shell重新解析已经展开的命令,这样大括号扩展就能正常生效:

# 先修正变量名错误
InicialMin=$(date -d "-5 minutes" +%M)
FinalMin=$(date +%M)
MinRange="${InicialMin}..${FinalMin}"

# 使用eval执行命令,注意变量转义
eval "Results=\$(ls -lrth /path/to/my/directory/SOMEFILES_20230922{$MinRange}.log | wc -l)"
echo "Files found: ${Results}"

⚠️ 注意:eval会执行任何传入的命令,要确保变量内容安全,这里因为变量是date生成的数字,没有注入风险,可以放心用。

方法2:用seq生成文件名序列

如果不想用eval,可借助seq生成范围内的所有数字,再通过大括号扩展拼接文件名:

InicialMin=$(date -d "-5 minutes" +%M)
FinalMin=$(date +%M)

# seq生成逗号分隔的数字,大括号扩展替换每个数字,屏蔽错误提示
Results=$(ls -lrth /path/to/my/directory/SOMEFILES_20230922{$(seq -s ',' $InicialMin $FinalMin)}.log 2>/dev/null | wc -l)
echo "Files found: ${Results}"

seq -s ','会生成类似30,31,32,33,34,35的字符串,大括号扩展会把每个数字替换进去,生成对应的文件名路径。2>/dev/null用来忽略不存在文件的报错信息。

方法3:用bash的printf生成模式串

bash的printf支持序列生成,可以直接构建出正确的文件名模式:

InicialMin=$(date -d "-5 minutes" +%M)
FinalMin=$(date +%M)

# 用printf生成带大括号范围的模式串
printf -v file_pattern "/path/to/my/directory/SOMEFILES_20230922{%d..%d}.log" "$InicialMin" "$FinalMin"
# 执行ls统计数量
Results=$(ls -lrth $file_pattern 2>/dev/null | wc -l)
echo "Files found: ${Results}"

printf -v把生成的模式存到file_pattern变量里,之后ls处理这个变量时,大括号扩展会正常生效。


内容的提问来源于stack exchange,提问作者André Escher

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 09:46:07