Bash 检查每分钟是否有一个文件

Bash 检查每分钟是否有一个文件,bash,Bash,我有一堆文件,文件名中有时间戳: A_2015-01-01_00-01 A_2015-01-01_00-02 A_2015-01-01_00-03 A_2015-01-01_00-04 文件夹中满是文件长达2个月,每分钟一个文件,我想知道是否有一种快速方法可以检查是否缺少时间戳,而无需使用例如包含所有时间戳的字典并运行比较。 因此,当一分钟的条目丢失,而这一分钟被跳过时,我会得到两个文件,它们围绕着丢失的分钟或时间范围。 我对一般的编码还不熟悉,我想知道这样的东西在bash脚本中是否可行 是否希

我有一堆文件,文件名中有时间戳: A_2015-01-01_00-01 A_2015-01-01_00-02 A_2015-01-01_00-03 A_2015-01-01_00-04

文件夹中满是文件长达2个月,每分钟一个文件,我想知道是否有一种快速方法可以检查是否缺少时间戳,而无需使用例如包含所有时间戳的字典并运行比较。 因此,当一分钟的条目丢失,而这一分钟被跳过时,我会得到两个文件,它们围绕着丢失的分钟或时间范围。
我对一般的编码还不熟悉,我想知道这样的东西在bash脚本中是否可行

是否希望脚本实时运行

如果是,那么也许你应该考虑一些类似的事情:

使用inotifywait监视文件夹中的新文件 对于每个新文件,检查是否存在名称为-1分钟的文件
您提供了一些不同格式的示例。假设实际格式为A_2015-01-01_00:04,这可能有助于:

#!/bin/bash

START="A_2015-01-01_00:01";
FINISH="A_2015-01-01_00:08";

NEXT_FILE="$START";
[ -f $NEXT_FILE ] || echo "$NEXT_FILE";

while [ "$NEXT_FILE" != "$FINISH" ];do
        TS=$(echo $NEXT_FILE | cut -d "_" -f2- | tr "_" " ");
        NEXT_MIN=$(date -d "$TS 1 minute" "+%Y-%m-%d_%H:%M");
        NEXT_FILE="A_$NEXT_MIN";
        [ -f $NEXT_FILE ] || echo "$NEXT_FILE";
done;
现在,使用A_2015-01-01_00-04格式


这将显示开始和完成之间缺少的文件,包括两者。您只需要定义START和FINSH文件。您可以修改脚本,以便将这些值作为参数提供。

您可以计算没有60个文件的时间。 当文件名完全按照问题中的说明构造时,您可以使用:

ls A_* | cut -d"-" -f1-3 | sort | uniq -c | grep -v " 60 "
救命啊

下面这个简单的脚本不会识别日期更改,但会给您跳过的分钟数

$ ls -1 | awk -F- 'p+1!=$NF{print p0, $0} {p=$NF;p0=$0}'
A_2015-01-01_00-04 A_2015-01-01_00-06
A_2015-01-01_00-08 A_2015-01-01_00-10
目录中有这些文件

$ ls -1
A_2015-01-01_00-01
A_2015-01-01_00-02
A_2015-01-01_00-03
A_2015-01-01_00-04
A_2015-01-01_00-06
A_2015-01-01_00-07
A_2015-01-01_00-08
A_2015-01-01_00-10

否则,为了获得更可靠的解决方案,您必须进行一些日历计算,以合并闰年等。

您的问题不是从目录中读取太多内容来制定检查,而是在两个日期之间生成文件名以检查是否缺少任何文件名。虽然bash在检查方面并不是最快的,但对于每隔两个月检查一次的时间来说,它就可以了

有很多方法可以解决这个问题,首先想到的一个方法是将开始和结束文件名作为参数,然后在日期之间生成文件名,然后检查每个文件是否存在,如果不存在,则抛出一个错误。基本上,实用程序seq将生成所需的序列。还有一些其他的实用程序更灵活一些,但是seq是无处不在的

设置逻辑采用多部分方法。基本上,您需要确定在开始和结束文件名之间需要测试什么。例如,如果一个部件的开始和结束时间少于一小时,则只需检查开始/结束之间的变化分钟数,等等

下面,我给出了处理以分钟递增的一个月的文件的逻辑示例。如果您觉得有必要,我会将多个月的实施留给您。如果格式发生更改,只需调整用于解析datestring每个部分的参数展开/子字符串删除。试一试:

#!/bin/bash

fstart="$1"  # starting filename
fend="$2"    # ending filename

## initial trim of filename from left
ystart=${fstart#*_}     # start year
mstart=${ystart#*-}     # start month
dstart=${mstart#*-}     # start day
Hstart=${dstart#*_}     # start Hour
Mstart=${fstart##*-}    # start Minute

yend=${fend#*_}     # end year
mend=${yend#*-}     # end month
dend=${mend#*-}     # end day
Hend=${dend#*_}     # end Hour
Mend=${fend##*-}    # end Minute

## final trim of filename from right
ystart=${ystart%%-*}
mstart=${mstart%%-*}
dstart=${dstart%%_*}
Hstart=${Hstart%%-*}

yend=${yend%%-*}
mend=${mend%%-*}
dend=${dend%%_*}
Hend=${Hend%%-*}

## base filename w/o day (e.g. A_2015-01)
fday=${fstart%_*}
fday=${fday%-*}

## check to end of first hour
for M in $(seq -f "%02g" $Mstart 59); do
    [ -e ${fstart%_*}_$Hstart-$M ] || printf " missing: %s\n" ${fstart%_*}_$Hstart-$M
    # printf " checking: %s\n" ${fstart%_*}_$Hstart-$M
done

## check remaining hours in 1st day
if ((dend > dstart)); then
    for H in $(seq -f "%02g" $((Hstart+1)) 23); do
        for M in $(seq -f "%02g" 0 59); do
            [ -e ${fstart%_*}_$H-$M ] || printf " missing: %s\n" ${fstart%_*}_$H-$M
            # printf " checking: %s\n" ${fstart%_*}_$H-$M
        done
    done
else
    for H in $(seq -f "%02g" 0$((Hstart+1)) $((Hend-1))); do
        for M in $(seq -f "%02g" 0 59); do
            [ -e ${fstart%_*}_$H-$M ] || printf " missing: %s\n" ${fstart%_*}_$H-$M
            # printf " checking: %s\n" ${fstart%_*}_$H-$M
        done
    done
    ## handle minues in last hour
    for M in $(seq -f "%02g" 0 $Mend); do
        [ -e ${fstart%_*}_$Hend-$M ] || printf " missing: %s\n" ${fstart%_*}_$Hend-$M
        # printf " checking: %s\n" ${fstart%_*}_$Hend-$M
    done
    printf "check complete\n"
    exit 0
fi

## check all hours in full or last day(s) between start/end
if ((dend > (dstart+1))); then  ## full days exist before end day
    for d in $(seq -f "%02g" $((dstart+1)) $((dend-1))); do
        for H in $(seq -f "%02g" 0 23); do
            for M in $(seq -f "%02g" 0 59); do
                [ -e ${fday}-${d}_$H-$M ] || printf " missing: %s\n" ${fday}-${d}_$H-$M
                # printf " checking: %s\n" ${fday}-${d}_$H-$M
            done
        done

    done
else    ## next day is last day (time spans < 48 hours)
    for H in $(seq -f "%02g" 0 $((Hend-1))); do
        for M in $(seq -f "%02g" 0 59); do
            [ -e ${fend%_*}_$H-$M ] || printf " missing: %s\n" ${fend%_*}_$H-$M
            # printf " checking: %s\n" ${fend%_*}_$H-$M
        done
    done
    ## handle minutes in last hour
    for M in $(seq -f "%02g" 0 $Mend); do
        [ -e ${fend%_*}_$Hend-$M ] || printf " missing: %s\n" ${fend%_*}_$Hend-$M
        # printf " checking: %s\n" ${fend%_*}_$Hend-$M
    done
    printf "check complete\n"
    exit 0    
fi

## Add Year/Month Iteration

exit 0
缺少A_2015-01-01_00-31的实际测试

作为一个简短的测试,创建了120个文件,其中包括:

$ touch A_2015-01-01_00-{00..59}
$ touch A_2015-01-01_01-{00..59}
删除A_2015-01-01_00-31并运行测试产生:

$ bash ../filepermin.sh A_2015-01-01_00-00 A_2015-01-01_01-59
 missing: A_2015-01-01_00-31
check complete
注意:可能有几种额外的方法来生成所需的序列。这是一种方法的一个例子。其他选项包括将所有文件名读取到一个数组中,以及对任何相距超过1的文件名进行顺序检查。但是,您随后会遇到本机文件排序的问题,两个月的时间是80K+个文件名。这就进入了bash速度非常慢的范围

通过将文件读入数组进行检查

如果您倾向于尝试将文件读入数组,那么在理解本机排序顺序可能会出现问题的情况下,并且知道您可以找到丢失文件周围的文件,但不确切地说是文件本身,可以采取更短的方法。只需切换到包含文件的目录,然后尝试以下操作:

#!/bin/bash

a=( * )
for ((i = 1; i < ${#a[@]}; i++)); do 

    n=${a[i]}               ## next date
    n=${n##*-}
    n=${n/#0/}

    p=${a[$((i-1))]}        ## prev date
    p=${p##*-}
    p=${p/#0/}

    [ $n -eq 0 ] && n=60    ## adjust for test on roll to next hour

    (((n - p) != 1)) && echo "file missing prior to ${a[i]}"

done

计算预计将出现的文件数,然后运行脚本,查看是否有以模式u开头的文件数。谢谢,这听起来很酷,但我忘了提到,我已经知道缺少了一些条目,但我想知道从哪一天开始缺少哪一分钟。所以我的计算告诉我有4分钟4个文件丢失。但是每分钟/24小时/大约2个月有一个文件。如何在bash中计算-1分钟的名称?这不会检测到文件完全停止出现的情况。不,我文件已经存在,我必须查看它们,以找到丢失的极少数不存在的文件来计算-1分钟的名称,您可以使用正则表达式,或者解析时间戳,然后将其向后1分钟。使用正则表达式,或者解析时间戳,然后将其向后1分钟-如何?感谢您的快速回复我更改了时间戳
对不起,弄错了。我会用修改过的版本更新答案很多。我会尝试一下,当我在OSX终端中输入它时,会遇到一些奇怪的循环,但我认为我应该让它工作。非常感谢你的代码。A_用法:日期[-jnu][-d dst][-r秒][-t西][-v[+|-]val[ymwdHMS]]。。。[-f fmt date |[[mm]dd]HH]mm[[cc]yy][.ss][+格式]我在centOS机器上使用Bash 3.2.25创建了这个。不确定它是否在OSX上工作。看起来date函数在OSX中的工作方式有所不同
$ bash ../filepermin.sh A_2015-01-01_00-00 A_2015-01-01_01-59
 missing: A_2015-01-01_00-31
check complete
#!/bin/bash

a=( * )
for ((i = 1; i < ${#a[@]}; i++)); do 

    n=${a[i]}               ## next date
    n=${n##*-}
    n=${n/#0/}

    p=${a[$((i-1))]}        ## prev date
    p=${p##*-}
    p=${p/#0/}

    [ $n -eq 0 ] && n=60    ## adjust for test on roll to next hour

    (((n - p) != 1)) && echo "file missing prior to ${a[i]}"

done
$ bash ../fpm.sh
file missing prior to A_2015-01-01_01-01