【问题标题】:Finding files containing occurrences of a string查找包含出现的字符串的文件
【发布时间】:2026-02-03 10:30:01
【问题描述】:

我的任务之一是计算与特定日期模式匹配的文件数量。我真正需要做的是遍历目录,检查每个文件名,找到该文件名中的第二个句点,然后检查接下来的 4 个字符,看看我正在组装的日期字符串是否匹配。

2012 年 11 月将表示为“1211”。在下面的文件名中使用第二个句点之后的前四个字符,这将使我们对第一个文件名(“o.tt.121113150804”)进行匹配,因为它与该模式匹配。我会计算那个文件,然后不理会其他两个。

以下文件只是一个示例。它们可以用许多不同的方式命名。它们通常只是低于 99% 时间的变体。虽然有 2 个句点,但我需要检查第 2 个句点之后的 4 个数字,这一事实是一个明确的常数。

我需要检查的文件名:

o.tt.121113150804
o.stpw.101209092541
i.rtat.120831045704

【问题讨论】:

  • 这是一个 bash 问题?

标签: shell unix grep


【解决方案1】:

这可以单独使用ls 完成,但这也将匹配目录:

$ ls
i.rtat.120831045704  o.stpw.101209092541  o.tt.121113150804

$ ls *.*.1121*
o.tt.121113150804

不过find 更强大更灵活:

$ find . -maxdepth 1 -type f -iname "*.*.1211*"
./o.tt.121113150804

选项:

-maxdepth 1 只看这个目录。

-type f 只查找文件,不查找目录。

-iname 使用模式匹配文件名,其中* 匹配任何内容,因此*.*.1211* 匹配任何内容,后跟.,后跟第二个.,后跟您的日期字符串和* 其他任何内容.

编辑:

要计算匹配的数量,您可以通过管道传递到 wc -l 并使用命令替换 $(...) 将值存储在变量中:

$ ls
i.rtat.120831045704  o.stpw.101209092541  o.tt.121113150804  
o.tt.121113150804c1  o.tt.121113150804c2

$ find . -maxdepth 1 -type f -iname "*.*.1211*" | wc -l
3

$ found=$(find . -maxdepth 1 -type f -iname "*.*.1211*" | wc -l)

$ echo $found
3

【讨论】:

  • 可能存在一个小问题,这似乎是检测名称中带有单点的文件名,例如a.12111231,操作似乎正在寻找第二个文件.。这find . -maxdepth 1 -type f -iname "*.*.1211*" 似乎工作。请看一下
  • @another.anon.coward 好点,这里不需要区分大小写,所以-name 就足够了,但我把它留了以防万一。感谢您的建议。
  • 无论我们使用何种 shell,都不喜欢 maxdepth 或 iname。但我可以解决这个问题。这很好用。非常感谢您的帮助。
  • 没问题,为了以后的参考,请确保做man find 看看你有哪些选项,它们可能会略有不同。
  • 会的。顺便说一句,您又看到了……您知道如何正确计算这些结果吗?所以如果 find 命令找到 5 个实例,它可以将其放入变量中?
【解决方案2】:

请注意,模式*.*.1211* 将匹配固定字符串前多于两个点 的文件。例如,a.b.c.1211 将匹配。

使用 bash 你可以写:

shopt -s extglob
ls  +([^.]).+([^.]).1211*

如果你只想数一数:

files=( +([^.]).+([^.]).1211* )
echo "${#files[@]} files matched"

【讨论】:

    【解决方案3】:

    @sudo_O 和 @glennjackman 回答了您的问题,但作为替代方案,如果您想一次获得所有日期的计数,您可以这样做

    ls | awk -F'.' '{count[substr($3,1,4)]++} END{for (date in count) print date, count[date]}'
    

    【讨论】: