![将给定日期范围内的所有日期存储到变量中](https://linux22.com/image/39279/%E5%B0%86%E7%BB%99%E5%AE%9A%E6%97%A5%E6%9C%9F%E8%8C%83%E5%9B%B4%E5%86%85%E7%9A%84%E6%89%80%E6%9C%89%E6%97%A5%E6%9C%9F%E5%AD%98%E5%82%A8%E5%88%B0%E5%8F%98%E9%87%8F%E4%B8%AD.png)
我想存储两个用户输入日期之间的所有可能日期。输入就像20140605和20140830。
我想使用循环将给定日期之间的每个日期存储到变量中,以便我可以使用它。
生成或计算的日期必须与输入的格式相同。
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