make getpeername() return the original socket address which before it was intercepted
[hband-tools.git] / user-tools / find-by-date
blob890fe24034e6dbada6d92e8bfd482ba9e0623f87
1 #!/bin/bash
3 true <<'EOF'
5 =pod
7 =head1 NAME
9 find-by-date - Find files with GNU find(1) but with easier to comprehend time interval formats
11 =head1 SYNOPSIS
13 find-by-date [I<FROM>--][I<TO>] [I<FIND-ARGS>]
15 =head1 DESCRIPTION
17 Takes your I<FROM>--I<TO> date-time specifications and turns into the
18 appropriative C<< -mmin -I<MINUTES> >> and C<< -mmin +I<MINUTES> >>
19 parameters for find(1), then call find(1).
21 =head1 SUPPORTED DATE FORMATS
23 Recognize these date-time formats in I<FROM> and I<TO>:
25 YYYY-mm-dd_HH:MM
26 YYYY-mm-dd_HH
27 YYYY-mm-dd
28 YYYY-mm
29 YYYY
30 mm-dd
32 mm-dd_HH:MM
33 mm-dd_HH
34 dd_HH:MM
35 dd_HH
36 HH:
37 _HH
39 Enter C<< 0--I<TO> >> to select any time up to I<TO>.
40 Enter C<< I<FROM>-- >> to select any time starting from I<FROM>.
42 =cut
44 EOF
46 set -u
47 set -e
48 set -E
49 set -o pipefail
50 trap 'echo "Internal error in ${FUNCNAME:-main}" >&2; exit -2' ERR
54 from=''
55 till=''
56 current_ts=`date +%s`
57 current_dt=`date +%Y%m%d%H%M -d @$current_ts`
58 current_Year=${current_dt:0:4}
59 current_month=${current_dt:4:2}
60 current_day=${current_dt:6:2}
61 current_Hour=${current_dt:8:2}
62 current_Min=${current_dt:10:2}
64 timeunits=(Year month day Hour Min)
66 declare -a formats
67 declare -A fmt
68 formats+=("YYYY-mm-dd_HH:MM")
69 fmt['([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})_([0-9]{1,2})[.:]([0-9]{1,2})']="Year month day Hour Min"
70 formats+=("YYYY-mm-dd_HH")
71 fmt['([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})_([0-9]{1,2})']="Year month day Hour"
72 formats+=("YYYY-mm-dd")
73 fmt['([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})']="Year month day"
74 formats+=("YYYY-mm")
75 fmt['([0-9]{4})-([0-9]{1,2})']="Year month"
76 formats+=("YYYY")
77 fmt['([0-9]{4})']="Year"
78 formats+=(" mm-dd")
79 fmt['([0-9]{1,2})-([0-9]{1,2})']="month day"
80 formats+=(" dd")
81 fmt['([0-9]{1,2})']="day"
82 formats+=(" mm-dd_HH:MM")
83 fmt['([0-9]{1,2})-([0-9]{1,2})_([0-9]{1,2})[.:]([0-9]{1,2})']="month day Hour Min"
84 formats+=(" mm-dd_HH")
85 fmt['([0-9]{1,2})-([0-9]{1,2})_([0-9]{1,2})']="month day Hour"
86 formats+=(" dd_HH:MM")
87 fmt['([0-9]{1,2})_([0-9]{1,2})[.:]([0-9]{1,2})']="day Hour Min"
88 formats+=(" dd_HH")
89 fmt['([0-9]{1,2})_([0-9]{1,2})']="day Hour"
90 formats+=(" HH:")
91 fmt['([0-9]{1,2})[:.]']="Hour"
92 formats+=(" _HH")
93 fmt['_([0-9]{1,2})']="Hour"
96 usage()
98 echo "Usage: $0 [from-date][\"--\"till-date] [find-parameters]
99 Date-time formats:"
100 for f in "${formats[@]}"
102 echo " $f"
103 done
104 exit -1
107 ago_min()
109 local ts
110 ts=`date +%s -d "$1"`
111 echo $[ ($current_ts - $ts) / 60 ]
114 parsedatetime()
116 local regex
117 local boundary=$1
118 local n=''
119 local timeunit
121 for timeunit in "${timeunits[@]}"
123 eval "${boundary}_$timeunit="
124 done
126 for regex in "${!fmt[@]}"
128 if [[ "${!boundary}" =~ ^$regex$ ]]
129 then
131 for timeunit in ${fmt[$regex]}
133 eval ${boundary}_$timeunit=${BASH_REMATCH[$n]}
134 n=$[n+1]
135 done
136 break
138 done
139 [ -n "$n" ] && return 0 || return 1
142 timeunit_limit()
144 case "$1" in
145 min|from)
146 case "$2" in
147 Year) echo 1970 ;;
148 month|day) echo 1 ;;
149 *) echo 0 ;;
150 esac
152 max|till)
153 case "$2" in
154 Year) false ;;
155 month) echo 12 ;;
156 day) date +%d -d "$3-$4-1 + 1 month - 1 day" ;;
157 Hour) echo 23 ;;
158 Min) echo 59 ;;
159 esac
162 false
164 esac
167 complete_times()
169 local boundary=$1
170 local miss=1
171 local n
172 local var val
173 local longer_timeunit longer_var longer_val
174 local shorter_timeunit shorter_var shorter_val
175 local var_Y var_m
176 local current_var current_val
177 local current_shorter_var current_shorter_val
179 while [ $miss -gt 0 ]
181 miss=0
182 for n in "${!timeunits[@]}"
184 timeunit=${timeunits[$n]}
185 var=${boundary}_$timeunit
186 val=${!var}
187 if [ -z "$val" ]
188 then
189 if [ $n = 0 ]
190 then
191 longer_val=''
192 else
193 longer_timeunit=${timeunits[$[n-1]]}
194 longer_var=${boundary}_$longer_timeunit
195 longer_val=${!longer_var}
198 if [ -n "$longer_val" ]
199 then
200 var_Y=${boundary}_Year
201 var_m=${boundary}_month
202 val=`timeunit_limit $boundary $timeunit ${!var_Y} ${!var_m}`
203 eval $var=$val
204 else
205 if [ $[n+1] -ge ${#timeunits[@]} ]
206 then
207 shorter_val=''
208 else
209 shorter_timeunit=${timeunits[$[n+1]]}
210 shorter_var=${boundary}_$shorter_timeunit
211 shorter_val=${!shorter_var}
214 if [ -n "$shorter_val" ]
215 then
216 if [ "$boundary" = till ]
217 then
218 current_var=from_$timeunit
219 current_shorter_var=from_$shorter_timeunit
220 cmp=-ge
221 ts=`date +%s -d "$from_Year-$from_month-$from_day $from_Hour:$from_Min"`
222 op=+
223 else
224 current_var=current_$timeunit
225 current_shorter_var=current_$shorter_timeunit
226 cmp=-lt
227 ts=$current_ts
228 op=-
230 current_val=${!current_var}
231 current_shorter_val=${!current_shorter_var}
233 if [ "$shorter_val" $cmp "$current_shorter_val" ]
234 then
235 eval $var=$current_val
236 else
237 dt=`date +%Y-%m-%dT%H:%M -d @$ts`
238 val=`date +%${timeunit:0:1} -d "$dt $op 1 $timeunit"`
239 eval $var=$val
241 else
242 miss=$[miss + 1]
246 done
247 done
251 if [ "$#" -lt 1 ]
252 then
253 usage >&2
254 exit -2
257 for arg in "$@"
259 if [ "$arg" = --help ]
260 then
261 usage
262 exit 0
264 done
266 #while [ $# -gt 0 ]
268 if [[ "$1" =~ ^(.*?)--(.*)$ ]]
269 then
270 from=${BASH_REMATCH[1]}
271 till=${BASH_REMATCH[2]}
272 elif [[ "$1" =~ ^(.*)--$ ]]
273 then
274 from=${BASH_REMATCH[1]}
275 elif [[ "$1" =~ ^0--(.*)$ ]]
276 then
277 till=${BASH_REMATCH[1]}
278 else
279 usage >&2
280 exit -2
282 shift
283 #done
285 # TODO support more intervals
287 for boundary in from till
289 if [ -n "${!boundary}" ]
290 then
291 parsedatetime $boundary
292 complete_times $boundary
294 done
298 declare -a find_opts
299 if [ -n "$from" ]
300 then
301 printf "From: %04d-%02d-%02d %02d:%02d\n" $from_Year $from_month $from_day $from_Hour $from_Min >&2
302 mins=`ago_min "$from_Year-$from_month-$from_day $from_Hour:$from_Min"`
303 find_opts+=(-mmin -$mins)
305 if [ -n "$till" ]
306 then
307 printf "Till: %04d-%02d-%02d %02d:%02d\n" $till_Year $till_month $till_day $till_Hour $till_Min >&2
308 mins=`ago_min "$till_Year-$till_month-$till_day $till_Hour:$till_Min"`
309 find_opts+=(-mmin +$mins)
312 find "${find_opts[@]}" "$@"