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 检查每分钟是否有一个文件,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脚本中是否可行 是否希
我对一般的编码还不熟悉,我想知道这样的东西在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