将给定日期范围内的所有日期存储到变量中

将给定日期范围内的所有日期存储到变量中

我想存储两个用户输入日期之间的所有可能日期。输入就像2014060520140830

我想使用循环将给定日期之间的每个日期存储到变量中,以便我可以使用它。

生成或计算的日期必须与输入的格式相同。

startdate=20141030
starttime=165800

enddate=20141120
endtime=175050

day=`expr $startdate % 100`
month=`expr $startdate % 10000`
year=`expr $startdate % 100000000`
month=`expr $month / 100`
year=`expr $year / 10000`
echo "$year  $month  $day"

while [ $enddate -ge $cdate ]
do
var=$cdate

#using variable var

if  [ $day -eq 31 ]; then
cdate=`expr $cdate - $day`
day=1
((month++))
cdate=`expr $cdate + 100 + $day`
#cdate=`expr $cdate + $day`
    if  [ $month -eq 13 ]; then
        #tmp=`expr $month \* 100`
        cdate=`expr $cdate - $month \* 100`
        month=1
        ((year++))
        cdate=`expr $cdate + 10100`
        if [ $year -eq 2999 ]; then
            ((year++))
            echo $cdate
            cdate=30010100
        fi
    fi
else
    ((day++))
    ((cdate++)) 
fi

if [ $enddate == $cdate ]; then
check=1
fi
done

我尝试以这种方式实现我的要求。但在编译时它说:

预期一元运算符

导致此错误的原因是什么?如何使用 shell 脚本更好地解决此问题?

答案1

我会采取完全不同的方法来解决这个问题。手动进行所有日期计算很容易出错(一个月并不总是 31 天,有闰年等)。再加上浏览代码,很难知道你在做什么(这是一件非常糟糕的事情)。

#!/bin/bash
startdate=20141030
enddate=20141120

dates=()
for (( date="$startdate"; date != enddate; )); do
    dates+=( "$date" )
    date="$(date --date="$date + 1 days" +'%Y%m%d')"
done
echo "${dates[@]}"

这使用该date命令来处理所有计算,并将每个日期存储在$dates数组中。

结果如下:

20141030 20141031 20141101 20141102 20141103 20141104 20141105 20141106 20141107 20141108 20141109 20141110 20141111 20141112 20141113 20141114 20141115 20141116 20141117 20141118 20141119

答案2

如果,正如您在评论中所解释的那样,您的最终目标是查找给定日期范围内修改的所有文件,那么将所述范围保存到变量中是毫无意义的。相反,您可以直接给出范围find

find . -mtime $start -mtime $end

就我个人而言,我会使用不同的方法。只需创建两个临时文件,一个在开始日期之前一秒创建,一个在结束日期之后一秒创建。然后使用 GNU find 的-newer测试来查找比第一个文件新且不比后者新的文件。

棘手的一点是获取$start$end正确。你可以尝试这样的事情:

#!/usr/bin/env bash

## If you really want to use this format, 
## then you must be consistent and always 
## us YYYYMMDD and HHMMSS.
startdate=20141030
starttime=165800

enddate=20141120
endtime=175050

## Get the start and end times in a format that GNU date can understand
startdate="$startdate $( sed -r 's/(..)(..)(..)/\1:\2:\3/' <<<$starttime)"
enddate="$enddate $( sed -r 's/(..)(..)(..)/\1:\2:\3/' <<<$endtime)"

## GNU find has the -newer test which lets you find files
## that are newer than the target file. We can use this
## and create two temporary files with the right dates.
tmp_start=$(mktemp)
tmp_end=$(mktemp)

## Now we need a date that is one seond before the
## start date and one second after the end date.
## We can then use touch and date to set the creation date 
## of the temp files to these dates. 
minusone=$(date -d "$startdate -1 sec" +%s)
plusone=$(date -d "$enddate +1 sec" +%s)

## Set the creation times of the temp files.
## The @ is needed when using seconds since
## the epoch as a date string.
touch -d "@$minusone" $tmp_start
touch -d "@$plusone" $tmp_end

## At this point we have two files, tmp_start and
## tmp_end with a creation date of $startdate-1 
## and $enddate+1 respectively. We can now search
## for files that are newer than one and not newer
## than the other.
find . -newer $tmp_start -not -newer $tmp_end

## Remove the temp files
rm $tmp_start $tmp_end

相关内容