2015-09-09 4 views
0

Я получил кучу файлов с метками времени в Имя файла:
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 месяцев, один файл в минуту, и мне было интересно. Если есть быстрый способ проверить, нет ли временной отметки без использования, например, словаря со всеми отметками времени и выполнения сравнения. Итак, для whenerver минута записи отсутствует, и поэтому эта минута пропущена. Я получаю два файла, окружающих эту недостающую минуту или таймфрейм. Я новичок в кодировании вообще и задавался вопросом, возможно ли что-то подобное с помощью сценария bash?

+0

Подсчитать количество файлов, как ожидается, будет присутствовать затем запустить сценарий, чтобы увидеть, если есть, что количество файлов, начиная с Pattern_. – Martin

+0

спасибо, что звучит круто, но я забыл упомянуть, что я уже знаю, что есть несколько пропусков, но я хочу знать, какая минута, с которой не хватает времени. Поэтому мои расчеты говорят мне, что есть 4 минуты (4 файла). Но есть файл каждые минуты/24 часа/прибл. 2 Month –

ответ

0

Вы представили некоторые примеры с другим форматом Предполагая, что реальный формат 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

#!/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-); 
     DAY=$(echo "$TS" | cut -d "_" -f1); 
     TIME=$(echo "$TS" | cut -d "_" -f2 | tr "-" ":"); 

     NEXT_MIN=$(date -d "$DAY $TIME 1 minute" "+%Y-%m-%d_%H-%M"); 
     NEXT_FILE="A_$NEXT_MIN"; 

     [ -f $NEXT_FILE ] || echo "$NEXT_FILE"; 
done; 

Это покажет недостающие файлы между START и FINISH, в том числе и. Вам просто нужно определить ваши файлы START и FINSH. Вы можете изменить сценарий, чтобы вы могли указать эти значения в качестве параметров.

+0

спасибо за быстрый ответ I изменил отметку времени, извините за ошибку –

+0

OK. Я обновлю ответ с измененной версией –

+0

Большое спасибо. Я дам ему попробовать –

0

Вы хотите, чтобы сценарий запускался в режиме реального времени?

Если да, то, возможно, вам следует рассмотреть что-то вроде:

  • контролировать папку для новых файлов (используйте inotifywait
  • для каждого нового файла, проверьте, существует ли файл с именем, имеющим -1 минуты
+0

Как вы вычисляете «имя, имеющее -1 минуту» в bash? – melpomene

+0

Это не обнаружит случая, когда файлы перестанут появляться полностью. – melpomene

+0

Нет, файлы уже есть, и я должен просмотреть их, чтобы найти (очень немного) несуществующих файлов, отсутствующих –

0

Вы можете рассчитывать на тот час, когда у вас 60 файлов. Когда имена файлов построены точно так, как указано в вопросе, вы можете использовать:

ls A_* | cut -d"-" -f1-3 | sort | uniq -c | grep -v " 60 " 
+0

отличный подход, спасибо, –

0

AWK на помощь!

Это следующее простой скрипт не распознают изменения даты, но даст вам Пропускаемые минуты,

$ 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 

в противном случае для более надежного решения, которое вы должны сделать некоторые календарные расчеты для включения високосных годов и т. д.

+0

спасибо большое, очень приятно one_liner –

0

Ваша проблема заключается не столько в чтении из каталога, сколько в формулировке ваших чеков, способ генерации имен файлов между двумя датами, чтобы проверить, отсутствуют ли какие-либо данные. Хотя bash не самый быстрый, когда дело доходит до проверки, для проверки двухмесячной стоимости минут раз в то время, это будет сделано.

Есть много способов подойти к проблеме, одна из первых, которая пришла на ум, - это просто взять имена и имена файлов в начале и конце, а затем сгенерировать имена файлов между датами, а затем просто проверить, существует ли каждый файл, и если нет, выведите ошибку. В принципе, утилита seq генерирует необходимые последовательности. Есть несколько других утилит, которые немного более гибкие, но seq вездесущ.

Настройка логики требует многоуровневого подхода. В основном вам нужно определить, что нужно тестировать между начальным и конечным именами файлов. Например, если начало и конец меньше часа, вам нужно всего лишь проверить изменения минут между началом/окончанием и т. Д.

Ниже я привел примеры логики обработки месяца ценность файлов увеличивается на минуты. Я оставил многомесячную реализацию для вас, если вы сочтете это необходимым. Если формат изменяется, просто отредактируйте удаление параметра/подстроки, используемое для синтаксического анализа каждой части самой даты. Дайте ему попробовать:

#!/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 

Выше вы видите тестовые printf заявления закомментирована. В качестве примера генерации имен файлов через изменяющиеся часы, имена, генерируемые являются:

Примера Проверка

$ bash filepermin.sh A_2015-01-01_23-50 A_2015-01-02_00-15 
checking: A_2015-01-01_23-50 
checking: A_2015-01-01_23-51 
checking: A_2015-01-01_23-52 
checking: A_2015-01-01_23-53 
checking: A_2015-01-01_23-54 
checking: A_2015-01-01_23-55 
checking: A_2015-01-01_23-56 
checking: A_2015-01-01_23-57 
checking: A_2015-01-01_23-58 
checking: A_2015-01-01_23-59 
checking: A_2015-01-02_00-00 
checking: A_2015-01-02_00-01 
checking: A_2015-01-02_00-02 
checking: A_2015-01-02_00-03 
checking: A_2015-01-02_00-04 
checking: A_2015-01-02_00-05 
checking: A_2015-01-02_00-06 
checking: A_2015-01-02_00-07 
checking: A_2015-01-02_00-08 
checking: A_2015-01-02_00-09 
checking: A_2015-01-02_00-10 
checking: A_2015-01-02_00-11 
checking: A_2015-01-02_00-12 
checking: A_2015-01-02_00-13 
checking: A_2015-01-02_00-14 
checking: A_2015-01-02_00-15 
check complete 

фактического испытания (с A_2015-01-01_00-31 отсутствует)

В качестве короткого теста было создано 120 файлов:

$ touch A_2015-01-01_00-{00..59} 
$ touch A_2015-01-01_01-{00..59} 

Удалениеи запустить тест дали:

$ 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 

Если какие-либо из next/prev имен файлов отличается более чем 1, сценарий будет флаг файл как отсутствующие до текущего файла.Например, удаление A_2015-01-01_01-00 из последовательности файлов вызовет:

$ bash ../fpm.sh 
file missing prior to A_2015-01-01_01-01 
Смежные вопросы