Bash: 根据文件名中的日期范围查找所有文件

Bash: find all files based on date range in file names

我有一个目录,其中包含许多按以下日期格式命名的文件:

YYYYMMDDHH00

最后有一个 com 端口号。例如

202003240200COM10.txt
202003240300COM10.txt
202003240400COM10.txt

这些文件由脚本每小时生成一次,名称始终采用相同的格式。

我想使用 "find" 命令来 return 我在脚本中指定的日期范围内的文件列表,例如“1 小时前”和“1 小时前”之间的所有文件一个月前”。该脚本将 运行 随机出现,我总是希望它在相对于当前日期的日期范围内进行搜索,因此我不需要任何硬编码日期。

我可以使用 "date" 命令获取 1 小时前和 3 个月前的日期:

bash-4.4$ date --date "1 hour ago" +%Y%m%d%H00
202003241500
bash-4.4$ date --date "1 month ago" +%Y%m%d%H00
202002241600

但我正在努力将它正确地放入 "find" 命令中。我尝试了以下方法:

for currentfile in *.txt
do
    filedate=${currentfile:0:12}
        file_date=$(date +%s -d "${filedate:0:8}${filedate:8:2}${filedate:10:2}${filedate12:2}")
        start_date=$(date +%s -d "1 month ago")
        end_date=$(date +%s -d "1 hour ago")

        if [[ $file_date -ge $start_date && $file_date -le $end_date ]]; then
                echo $currentfile
        fi
done

但是控制台输出只是一大堆这些错误,似乎每个文件都有一个:

date: invalid date 201703190300
date: invalid date 201703190400
date: invalid date 201703190500
date: invalid date 201703190600
date: invalid date 201703190700
date: invalid date 201703190800
date: invalid date 201703190900
date: invalid date 201703191000
date: invalid date 201703191100
date: invalid date 201703191200
date: invalid date 201703191300
date: invalid date 201703191400
date: invalid date 201703191500
date: invalid date 201703191600
date: invalid date 201703191700
date: invalid date 201703191800
date: invalid date 201703191900

请帮忙:)

date -d 期望日期和时间部分之间有一个 space。 "CO" 不是时间戳的有效部分,因此将其删除(原始代码中有错字导致未设置变量)并用冒号分隔小时和分钟:

file_date=$(date +%s -d "${filedate:0:8} ${filedate:8:2}:${filedate:10:2}")

我使用

创建了测试文件
touch 20200{1,2,3,4}2{3,4,5}0200COM{1,2,3}0.txt 

运行下面的脚本

#!/bin/bash

start_date=$(date +%s -d "1 month ago")
end_date=$(date +%s -d "1 hour ago")

for currentfile in *.txt ; do
    file_date=$(date +%s -d "${currentfile:0:8} ${currentfile:8:2}:${currentfile:10:2}")

    if [[ $file_date -ge $start_date && $file_date -le $end_date ]]; then
        echo $currentfile
    fi
done

只打印了正确的:

202002250200COM10.txt
202002250200COM20.txt
202002250200COM30.txt
202003230200COM10.txt
202003230200COM20.txt
202003230200COM30.txt
202003240200COM10.txt
202003240200COM20.txt
202003240200COM30.txt

正如 Léa Gris 在评论中正确指出的那样,您可以直接使用 YYYYMMDDhhmm 格式并将时间戳作为字符串进行比较。这样你根本不需要在循环内调用 date:

#!/bin/bash

start_date=$(date +%Y%m%d%H%M -d "1 month ago")
end_date=$(date +%Y%m%d%H%M -d "1 hour ago")

for currentfile in *.txt ; do
    file_date=${currentfile:0:12}
    if [[ ! $file_date < $start_date && ! $file_date > $end_date ]]; then
        echo $currentfile
    fi
done

请注意 >= 运算符不存在,因此我们必须使用取反 <.

由于这个问题已经有了答案,我可能会建议一种不依赖于正确文件名的替代方法。相反,您可以只读取文件的元数据并相应地打印它们。第一个日期是最近的。

find . -mtime $(date +%s -d "1 hour ago") -mtime $(date +%s -d "1 month ago")

这可能更可靠,也适用于其他日志记录应用程序。