2017-01-04 1 views
0

Я пишу скрипт BASH, который, между прочим, копирует файлы из одного каталога в другой на основе входных аргументов для дат начала и окончания. Имена файлов имеют формат YYYYMMDDhhmmss.jpg, например. 20161230143922.jpg. Я использую find ... -exec cp {} ..., потому что в исходном каталоге есть десятки тысяч файлов. Входными аргументами являются дата начала и окончания в формате YYYYMMDD.BASH найти регулярное выражение для произвольного диапазона чисел в большом количестве файлов

Я знаю, что я не могу сделать простой диапазон в регулярном выражении, например ($startdate..$enddate), но я не могу понять, как программно генерировать регулярное выражение, которое будет работать. Если бы у меня было меньше файлов, я мог бы просто сделать cp {$startdate..$enddate} destination, но, увы, я не думаю, что это возможно.

Я хотел бы, чтобы скопировать все файлы между $startdate и $enddate, которые попадают между часами 0500 и 1700. Это будет включать в себя изображения, как 20170102060635.jpg и 20170104131255.jpg, но не 20170103010022.jpg.

Это то, что я до сих пор:

#!/bin/bash 

STARTDATE=$1 
ENDDATE=$2 
FILE_NAME="review-${STARTDATE}-${ENDDATE}.mp4" 

if [[ -n "$STARTDATE" ]]; then 
    echo "STARTDATE: $STARTDATE" 
else 
    echo "Invalid start date: '$STARTDATE'" 
    echo "Syntax: ./create_time_lapse_date_range.sh <startdate> <enddate>" 
    exit 
fi 

if [[ -n "$ENDDATE" ]]; then 
    echo "ENDDATE: $ENDDATE" 
else 
    echo "Invalid end date: '$ENDDATE'" 
    echo "Syntax: ./create_time_lapse_date_range.sh <startdate> <enddate>" 
    exit 
fi 

cd ~/Desktop/test\ timelapse 

# Copy relevant files to local directory 
find ~/Desktop/originals -regex "???????????????" -exec cp {} ~/Desktop/test\ timelapse/ \; 

# Rename files to be sequential serial numbers 
find ~/Desktop/test\ timelapse -name "*.jpg" | awk 'BEGIN{ a=0 }{ printf "mv \"%s\" ~/Desktop/\"test\ timelapse/%06d.jpg\"\n", $0, a++ }' | bash 

# Generate timelapse video 
ffmpeg -framerate 25 -i %06d.jpg -c:v libx264 -r 25 ${FILE_NAME} 
+0

Вы можете создать функцию, которая будет разделена дату и время из файла и сравнить их к соответствующим границам. –

ответ

1

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

REGEX="([0-9]{8})([0-9]{4})" 

for f in ~/Desktop/originals/*.jpg 
do 
    if [[ $f =~ $regex ]] 
    then 
     datepart=${BASH_REMATCH[1]} 
     timepart=${BASH_REMATCH[2]} 

     #if the DATE part matches 
     if (($STARTDATE <= $datepart)) && (($datepart <= $ENDDATE)) 
     then 
      #if the TIME part matches 
      if [[ $timepart =~ "(0[5-9]|1[0-7])" ]] 
      then 
       # copy file ... 
      fi 
     fi 
    fi 
done 

Pure Regex Решение

Если вы действительно хотите, чистое решения регулярного выражения, это поможет продемонстрировать сложность. Вот регулярное выражение, чтобы найти все файлы в 0500 до 1700 таймфрейме, для даты в январе 2017 года: ^201701\d{2}(0[5-9]|1[0-7])\d{4}\.jpg$

Обратите внимание на регулярное выражение шаблон требуется, чтобы соответствовать времени от 0500 до 1700:

(0[5-9]|1[0-7])

Это не довольно, и это с жестко запрограммированным диапазоном. Чтобы иметь дело с динамическими датами начала и окончания, вы будете строить аналогичную модель динамически. Это можно сделать, но зачем использовать для этого регулярное выражение?

Вот пример, показывающий, что вам нужно будет произвести для диапазона дат от 20161225 до 20170114:

^(201612(2[5-9]|3\d)|201701(0\d|1[0-4]))(0[5-9]|1[0-7])\d{4}\.jpg$

+0

@ryan, я добавил несколько примеров кода к моему ответу, чтобы дать более полное решение. –

Смежные вопросы