11
Nov
09

more ruby find code


The majority of the scripts I write make heavy use of the find module. Today it took me about two hours to debug one of them. It was a regex issue, and the wrappers I built around find weren’t that well thought out. Later today, I wrote this :


module FindTools
	extend self
	def find_matching(hash)
		where = hash[:where] || "."
		conditions = hash[:conditions] || []
		select_callback = hash[:select_callback] || lambda {|f|}
		all_files_callback = hash[:all_files_callback] || lambda {|f|}
		files = []
		matches = false
		Find.find(where) do |file|
			all_files_callback.call(file)
			matches = true
			select_file = true
			conditions.each do |condition|
				res = condition.call(file)
				matches = false if !res
			end
			if matches
				select_callback.call(file)
				files << file
			end
		end
		return files
	end
end

and you can use it like this:


files = FindTools.find_matching(
	:where => ARGV[0],
	:conditions => [
		lambda {|file| File.directory?(file)},
		lambda {|file| file !~ /thunder|firefox|chrome/i}
	],
)

You can chain an unlimited number of lambdas/procs here, the only prerequisite is that the callback has a call method. You can add two more callbacks here :


files = FindTools.find_matching(
	:where => ARGV[0],
	:conditions => [
		lambda {|file| File.directory?(file)},
		lambda {|file| file =~/\d+/i},
		lambda {|file| file !~ /flash|google/i},
		lambda {|file| file !~ /cygwin|wing|temp/i},
		lambda {|file| file !~ /thunder|firefox|chrome/i}
	],
	:select_callback => lambda {|f| puts f}
)

The select_callback fires every time a file passes all conditions. You can also use the all_files_callback like this:


files = FindTools.find_matching(
	:where => ARGV[0],
	:conditions => [
		lambda {|file| File.directory?(file)},
		lambda {|file| file =~/\d+/i},
		lambda {|file| file !~ /flash|google/i},
		lambda {|file| file !~ /cygwin|wing|temp/i},
		lambda {|file| file !~ /thunder|firefox|chrome/i}
	],
        :all_files_callback => lambda {|f| puts f}
)

and this will fire on all files found by find, no matter if they passed the conditions or not.

I know this is the Nth post you read about finding stuff here, but, what can I say? I find this to be the most important task when automating stuff.

10
Nov
09

ruby method currying


Just wanted to share this link with you. Basically, this is how you can curry a method in Ruby:


class Object
   def curry(method,*params)
      lambda { send method,*params }
   end
end

Thanks Marcos Toledo!

09
Nov
09

30k


Today I had the 30.000th visit on this blog. Thanks!

08
Nov
09

strangers we’ve become

04
Nov
09

hara – ploua stele

01
Nov
09

using java for common scripting tasks:walking directories & processing files


I’m a fan of scripting languages. If you read some of the stuff I wrote, you may already know that ( if not, check the URL of this website ). You can solve many/all tasks using a scripting language, but, sometimes you’d like to benefit from the speed that a typed language can give you. I think the most frequent task one has to do is process files. But, to do that, first you have to find them, scan directories, filter them, store them in some collection, and only then you can start processing them.

One of the downsides is that usually, code that would take several lines in a language like let’s say Ruby, becomes pretty verbose in Java. Here’s a sample:


Find.find(folder) do |file|
   puts file if File.directory?(file)
end

The code listed above will print all the directories ( and subdirectories ) contained in the folder parameter. 3 lines! Imagine how many you’d have to write in Java. You don’t have a built-in directory walker, so you’d need to roll your own methods/class.
Then, you would want your walker to be usable in all the tasks you may encounter, so that you don’t have to rewrite the whole thing when you need to enumerate all the zip archives inside a folder, or mp3’s. Usually, writing methods that accept callbacks is a great practice. In fact, the code written above illustrates that concept exactly. The stuff contained between the do and end is a block, Ruby’s way of implementing callbacks.
In Java, we don’t have first class functions, but we can achieve kinda the same thing by using interfaces. How does the following Java code look like:


File directory = new File("c:/");
FileWalker.walkDirectory(directory, new Callback<File>() {
        public void action(File t) {
             if(t.isDirectory())
                 System.out.println(t);
        }
});

I’d say it’s not that bad! You can live with that, right? What if you’d like to add them to a list and process them later? The following snippet shows you how to do that:


File directory = new File("c:/");
final ArrayList<File> results = new ArrayList<File>();
FileWalker.walkDirectory(directory, new Callback<File>() {
     public void action(File t) {
        if(t.isDirectory())
           results.add(t);
     }
});
for(File result : results)  {
    System.out.println(result);
}

I don’t know about you, but most ( if not all ) directory walking and file searching stuff I do, involves getting a list of files first, and processing them later. So that I don’t have to write all that code when I need to do this, I created a selectFiles method which does exactly that: return a list of files matching a certain condition. Here’s an example of it’s usage:


File directory = new File("c:/");
ArrayList>File> results = FileWalker.selectFiles(directory, new Selector>File>(){
    public boolean accept(File t) {
       return t.isDirectory();
    }
});
for(File result : results)
{
    System.out.println(result);
}

It doesn’t save you that many keystrokes, but it saves you from declaring a list, and doing everything inside a callback. Think of that Selector as a Filter. Here’s the code behind all the classes showed here:
The Selector interface:


public interface Selector<T> {
    public boolean accept(T t);
}

The Callback interface:


public interface Callback<T> {
    public void action(T t);
}

And the FileWalker class:


public class FileWalker {

    /**
     * select all files from a folder, matching a condition
     * @param root folder
     * @param selector selector object
     * @return list of files matching criteria
     */
    public static ArrayList<File> selectFiles(final File root,final Selector<File> selector)
    {
        final ArrayList<File> files = new ArrayList<File>();
        FileWalker.walkDirectory(root, new Callback()
        {

            public void action(File t) {
                boolean add = true;
                if(selector != null)
                {
                    add = selector.accept(t);
                }
                if(add) { files.add(t); }
            }

        });
        return files;
    }

    /**
     * walk a directory recursively
     * @param root folder
     * @param callback callback object
     */
    public static void walkDirectory(File root,Callback<File> callback)
    {
        File kids[] = root.listFiles();
        callback.action(root);
        if(kids != null)
        {
            for(File kid : kids)
            {
                walkDirectory(kid,callback);
            }
        }
    }

}

Whenever I get the chance, I do this sort of stuff in Ruby/Groovy/Python. I prefer development speed over execution speed. But, sometimes, you just can’t afford going into a dynamic language, and using plain Java for this sort of tasks looks like something you can cope with. Hang in there! :)

31
Oct
09

halp retarded kitty


Hilarious:
lolcats funny cat pictures

31
Oct
09

endurance boost


Last training, I was able to last about 10 minutes. Now I managed 13:10. Big improvement.