· 8 years ago · May 25, 2018, 01:34 PM
1#!/bin/bash
2#
3# Run periodically by cron, and will unarchive data in the
4# ~/auto_unarchive/drop_target directory.
5
6# Where the action happens
7unarchiveDir="~/auto_unarchive/drop_target"
8
9# Time in seconds between checking for new archives
10checkInterval=1.5
11
12# Total number of seconds the script should run for before
13# exiting.
14runTime=59
15
16# If non-empty, some extra messages will be logged.
17# This should be off for long-term cron use, as it will bloat
18# the logs.
19verbose=""
20
21# Flag used to log when killed.
22cleanExit=""
23
24# Will only run if this file doesn't exist
25lockFile="$unarchiveDir/.unarchive.lock"
26
27# Hash table of archive types to their extraction commands.
28# The keys are used to grep the output of the file command.
29# Used by: getNextArchive,
30extractKeys[0]=Zip; extractCmds[0]="unzip"
31extractKeys[1]=gzip; extractCmds[1]="gunzip"
32
33function printUsage()
34{
35 local scr="`basename $0`"
36
37 echo "usage: $scr [--help | -h]"
38}
39
40# Create the unarchive dir if necessary, and return true iff it
41# exists.
42function setupDir()
43{
44 local targetDir="$1"
45
46 if [ ! -d "$targetDir" ]; then
47 log "Creating auto unarchive directory: $targetDir" <(mkdir "$targetDir")
48 fi
49
50 if [ -d "$targetDir" ]; then
51 return 0
52 else
53 return 1
54 fi
55}
56
57# Returns true only if this instance of the script currently
58# owns the lock on the unarchiving directory
59function tryLock()
60{
61 if [ ! -f "$lockFile" ]; then
62 echo "$$" >"$lockFile"
63 return 0
64 else
65 return 1
66 fi
67}
68
69# Releases the lock on the unarchiving directory if this script
70# currently holds it
71function unlock()
72{
73 # If this instance of the script currently owns the lock
74 if [ $$ = "$(cat "$lockFile" 2>/dev/null)" ]; then
75 rm -f "$lockFile"
76 return 0
77 fi
78
79 return 1
80}
81
82# Prints the index of the extract key/command for a file.
83# $1 - the filename whose type to search for
84function findExtractIndex()
85{
86 fileName="$1"
87 i=${#extractKeys[*]}
88 i=$(($i - 1))
89
90 if [ "$fileName" ]; then
91 while [ $i -ge 0 ]; do
92 key="${extractKeys[$i]}"
93
94 if [ "$(file "$line" | grep "$key")" ]; then
95 echo $i
96 return 0
97 fi
98
99 i=$(($i - 1))
100 done
101 fi
102
103 return 1
104}
105
106# Prints the absolute path of a relative path, relative to the
107# current directory.
108# $1 - the path to make absolute
109function absolutePath()
110{
111 path="$1"
112
113 if [ "$1" ]; then
114 # Clean leading ./ (e.g. from find command output)
115 if [ './' = "${path:0:2}" ]; then
116 path="${path:2}"
117 fi
118
119 # Prepend working dir onto non-absolute paths
120 if [ '/' != "${path:0:1}" ]; then
121 echo "$(pwd)/$path"
122 else
123 echo "$path"
124 fi
125 fi
126}
127
128# Prints the extract command for a file, ready-to-run.
129# $1 - the file to get the extract command for
130# $2 - (optional) the index in the extract table. If not
131# specified, will search the table.
132function getExtractCmd()
133{
134 fileName="$(absolutePath "$1")"
135 index="$2"
136 [ -z "$index" ] && index="$(findExtractIndex "$fileName")"
137
138 if [ "$index" ]; then
139 # Construct the runnable command and return true
140 echo "${extractCmds[$index]} '$fileName'"
141 return 0
142 fi
143
144 return 1
145}
146
147# Prints the name of an archive in the current directory,
148# or nothing if there are no archives.
149# If there is an archive, prints the index in the extract
150# table on the second line.
151function getNextArchive()
152{
153 find . -maxdepth 1 -type f | while read line; do
154 index="$(findExtractIndex "$line")"
155
156 if [ "$index" ]; then
157 echo "$line"
158 echo $index
159 return 0
160 fi
161 done
162
163 return 1
164}
165
166# Extracts a file into directory above unarchive directory.
167# $1 - filename of archive
168# $2 - (optional) index in extract table
169function extractFile()
170{
171 fileName="$1"
172 index="$2"
173 [ -z "$index" ] && index="$(findExtractIndex "$fileName")"
174 cmd="$(getExtractCmd "$curFile" "$index")"
175
176 # Perform the extract and capture the output
177 extractLog="$( (
178 cd ..
179 echo "Changed to directory '$(pwd)'."
180
181 eval $cmd
182 ) 2>&1)"
183 extractResult=$?
184
185 # Log the output
186 echo -n "$extractLog" | log "Found archive '$curFile', extracting: $cmd"
187# log "Found archive '$curFile', extracting: $cmd"
188# echo "$extractLog" | while read l; do log "$l"; done
189
190 if [ $extractResult -eq 0 ]; then
191 (
192 [ ! -d "extracted" ] && mkdir extracted
193 mv "$fileName" extracted/
194 ) 2>&1 | log "Extraction successful, deleting '$fileName'..."
195 return 0
196 else
197 log "Extraction failed."
198 return 1
199 fi
200}
201
202function exitHandler()
203{
204 unlock
205
206 if [ "$cleanExit" ]; then
207 [ "$verbose" ] && log "Finished monitoring '$unarchiveDir' (ran for $SECONDS seconds), exiting."
208 else
209 log "Killed after $SECONDS seconds, aborting monitoring '$unarchiveDir'."
210 fi
211}
212
213# Process user-specified flags
214while [ "`echo "$1" | grep -E -e '^-.'`" ]; do
215 case "$1" in
216 --help|-h)
217 printUsage
218 exit 0
219 ;;
220 *)
221 printUsage
222 exit 1
223 ;;
224 esac
225 shift
226done
227
228# Make sure directory is unlocked if the script is killed
229trap "exitHandler" EXIT
230
231if setupDir "$unarchiveDir"; then
232 cd "$unarchiveDir"
233
234 [ "$verbose" ] && log "Monitoring '$unarchiveDir' for $runTime seconds, at $checkInterval intervals..."
235
236 while [ $SECONDS -le "$runTime" ]; do
237 # Only continue if there are no other instances of
238 # this script running.
239 if tryLock; then
240 # Get the filename and index of the next archive
241 nextArchive="$(getNextArchive)"
242
243 # Process all archives in the current directory before sleeping
244 while [ "$nextArchive" ]; do
245 curFile=""
246 curIndex=""
247 cmd=""
248
249 echo "$nextArchive" | (
250 read line && curFile="$line"
251 read line && curIndex="$line"
252 cmd="$(getExtractCmd "$curFile" $curIndex)"
253
254 extractFile "$curFile" "$curIndex"
255 )
256
257 nextArchive="$(getNextArchive)"
258 done
259
260 unlock
261 fi
262
263 sleep "$checkInterval"
264 done
265
266 cleanExit="true"
267fi