2つのユーザー入力日の間に可能なすべての日付を保存したいと思います。入力は次のとおりです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
私はこのように要件を実装しようとしています。ただし、コンパイル時には次のように言います。
単項演算子が必要です。
このエラーの原因は何ですか?シェルスクリプトを使用してこの問題をどのように解決するのですか?
答え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
個人的に私は別のアプローチを使用したいと思います。開始日の1秒前と終了日の1秒後の2つの一時ファイルを作成するだけです。次に、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