Armazena todas as datas em um determinado intervalo de datas em uma variável

6

Eu quero armazenar todas as datas possíveis entre duas datas de entrada do usuário. A entrada será como 20140605 e 20140830 .

Eu quero armazenar cada data entre as datas dadas em uma variável usando um loop para que eu possa usá-lo.

A data gerada ou calculada deve estar no mesmo formato da entrada.

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

Eu tentei implementar meu requisito dessa maneira. Mas na compilação diz:

unary operator expected

Qual é a causa desse erro e como posso fazer isso de uma maneira melhor usando um script de shell?

    
por FredOscatore 07.07.2014 / 13:38

2 respostas

11

Eu tomaria uma abordagem completamente diferente disso. Fazer todos os cálculos de data à mão é propenso a erros (nem sempre há 31 dias em um mês, você tem anos bissextos, etc). Além de escanear seu código, é muito difícil dizer o que você está fazendo (o que é uma coisa muito ruim).

#!/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[@]}"

Isso usa o comando date para manipular todos os cálculos, armazenando cada data na matriz $dates .

O resultado é assim:

20141030 20141031 20141101 20141102 20141103 20141104 20141105 20141106 20141107 20141108 20141109 20141110 20141111 20141112 20141113 20141114 20141115 20141116 20141117 20141118 20141119
    
por 07.07.2014 / 15:05
3

Se, como você explicou em seus comentários, seu objetivo final aqui é encontrar todos os arquivos modificados dentro de um determinado período, salvar o referido intervalo em uma variável é inútil. Em vez disso, você pode fornecer o intervalo para find diretamente:

find . -mtime $start -mtime $end

Pessoalmente, eu usaria uma abordagem diferente. Basta criar dois arquivos temporários, um criado um segundo antes da data de início e um criado um segundo após a data de término. Em seguida, use o -newer test do GNU find para encontrar arquivos mais novos que o primeiro e não mais recentes que o último.

O bit complicado está recebendo $start e $end corretamente. Você poderia tentar algo como:

#!/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/(..)(..)(..)/::/' <<<$starttime)"
enddate="$enddate $( sed -r 's/(..)(..)(..)/::/' <<<$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
    
por 07.07.2014 / 15:14