POSIX glob -- 如何匹配一个或多个 [:digit:]

POSIX glob -- how to match one-or-more [:digit:]

我想遍历 foo.log 及其日志轮换兄弟 foo.1.gzfoo.2.gz 从最新到最旧,代码不会被 [=14 的存在所迷惑=]

令人高兴的是,logrotate 命名事物时,最新到最旧的顺序和字母顺序相同。

我最初的尝试是 for f in $(ls -t foo.*); do ...shellcheckIterating over ls output is fragile. Use globs. [SC2045]。另外,此代码匹配不需要的 foo.bar

但是如何将任意数量的数字与 glob 模式匹配?(或者这不被支持?)我只知道如何明确列出每个数字。例如,以下处理 1 位和 2 位数字并正确排除 foo.1bar.gz 但不处理 foo.123.gz (我没有做正确的事情导致 globing 发生!)

for f in foo.log foo.[[:digit:]].gz foo.[[:digit:]][[:digit:]].gz; do ...

我可以假设没有人保留超过 100 个日志轮换的兄弟姐妹,但我不想这样做。

正在寻找 POSIX 兼容的解决方案...

编辑:logrotate conf 压缩一些文件而不压缩其他文件。所以并不是所有的兄弟姐妹都以 .gz.

结尾

glob 模式不是正则表达式。有关语法,请参阅 glob(7)。

没有匹配一系列数字的 glob 模式。你可以接近foo.[0-9]*.gz。如果那选择了一些你不想要的名字,你可以用正则表达式过滤掉它们,可能是这样的:

echo foo.[0-9]*.* | tr ' ' \n | grep -E '[.][0-9]+([.]gz)?$' 

考虑到您提出的限制条件,您或许可以使用 glob 模式并依靠 shell 进行排序。您可以使用 sort:

检查 shell 是否按排序顺序呈现 glob 模式的文件名
echo foo.[0-9]*.gz | tr \  \n | sort -c

但也可以解析 ls -t 的输出,除非您 非常 严格。来自 shellcheck 的指导是一个很好的建议:许多人似乎想要解析 ls 输出,而一个简单的 glob 就可以,并且依赖 ls 在不同系统中以相同的方式运行是邀请错误。也就是说,您只要求 ls 按时间对文件名进行排序,从而生成单列输出。您可能做的任何其他事情都更容易出错。

因为[:digit:]表示[0-9],如果要匹配一个或多个数字,请连用“一个或多个”运算符。

结果: +([0-9])

需要测试 glob 模式? DigitOceans 在此处发布了一个不错的工具。 https://www.digitalocean.com/community/tools/glob

祝你好运!