BASH在大量文件中查找任意数字范围的正则表达式

时间:2017-01-04 19:47:48

标签: regex linux bash unix find

我正在编写一个BASH脚本,除其他外,它根据开始日期和结束日期的输入参数将文件从一个目录复制到另一个目录。文件名的格式为YYYYMMDDhhmmss.jpg,例如20161230143922.jpg。我正在使用find ... -exec cp {} ...,因为源目录中有数万个文件。输入参数是格式为YYYYMMDD的开始日期和结束日期。

我知道我不能在($startdate..$enddate)这样的正则表达式中做一个简单的范围,但我无法弄清楚如何以编程方式生成一个可行的正则表达式。如果我的文件较少,我可以cp {$startdate..$enddate} destination,但唉,我认为这不可行。

我想复制介于0500和1700之间的$startdate$enddate之间的所有文件。这包括20170102060635.jpg20170104131255.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}

1 个答案:

答案 0 :(得分:1)

正则表达式不是处理数值范围的最佳工具,因此您可能需要考虑在正则表达式本身之外包含一些逻辑的解决方案。像这样:

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

纯正则表达式解决方案

如果您真的想要纯正的正则表达式解决方案,这将有助于展示复杂性。这是一个正则表达式,用于查找2017年1月的日期0500到1700时间范围内的所有文件:^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$