Date and Shell Find in Ruby
I was writing a small script to do backups on my local machine. Before this I was doing backups manually. To make this easier I came up with a naming scheme, with a dream to automate this.
Today the dream came true.
The scheme is really simple: Distinct_name_for_a_resource-DATE[-comment].(tar.gz|7z)
DATE is of format YYYYMMDDHHSS – no separators.
Sorting is really easy.
That’s the background. The tool finds if there have been any modified files in the directory being backed up and backs up the whole thing if so (no incremental backups). I wanted to use find as the tool for searching. Imagine my surprise when I could not find the key to give find a date for comparison.
There are keys of type -mtime and -mmin, which are relative to current time and specify an offset in days and minutes respectively. But I wanted a date.
It is possible of course to use -newer flag, which takes a filename and finds all, which are newer than that. It is possible to create a file with a specific date with
`touch -d DATE filename` output = `find PATH -newer filename` if (output.size > 0) # you found something end
However, there is a better solution. It is not really convinient when using from command line – it involves some computation. In this particular case, I use find inside a script, therefore it is perfectly appropriate.Reinventing the wheel is not an option – takes too much time to write and run. It would be relatively easy to write a ruby-based traversal with this single test. If not for the fact that I love to backup large quantities of files and really hate waiting. So let’s use find – it is implemented in C with lots of optimisations – should work faster than some ruby code comparing ruby date objects. It is quite easy:
tnow = Time.now
last_archive =~ /(#{prefix}-)([0-9]{12})([-.].*)/
puts "Found last backup: #{last_archive}"
time = get_time_from_string($2) # converts the 12 char string to Time obj
# Convert to minutes
minutes = ((tnow - time) / 60.0).floor
# Search
out = `find #{path} -mmin -#{minutes}`
archive_it = out.size > 0
puts "Files were modified" if archive_it
And that is it, no rocket science. Note, that one needs to use ‘-#{minutes}’ to tell find to use <= operator rather than just == without the ‘-’.Why not use DateTime if we need both the date and the time? Apparently the performance of DateTime is much worse than Time, and they have the same functionality.
ActionWebService::Struct – Complex Data Structures
December 16, 2007
Filed under Ruby
Tags: aws, data structures, rails, Ruby, struct, web service
Problem
Sometimes it is very useful to have something a little bit more complex inside a ActionWebService::Struct than the base types, arrays or other ActionWebService::Struct types. But this is hard to accomplish as the complex data structures, are not transportable by the web service layer (e.g. SOAP libraries cannot map them to a soap definition).
February 9, 2008