First: Use MacRuby. The latest MacRuby has Grand Central dispatching built in -- that's the Snow Leopard spiffiness that automatically manages multicore threading, etc. You may not need all that, but if you know it's only going to run on a Mac, why not?
Second: Get the 1.9 edition of the Pickaxe book (that's Programming Ruby 1.9) and read the entire chapter on threads, fibers, and processes.
Third: Adapt what you learn to your own needs, but I'd probably approach the problem by spinning off a new Thread
for each task and then running a system
or `backtick` call for each utility within its own thread. Ruby 1.9 has real threads (and MacRuby has better ones), so these really would all run at once -- and interpreter locking doesn't matter at all if you're mostly waiting on external processes.
(If you didn't need to pay attention to the results of the calls and didn't need to loop, the Pickaxe's example of exec('foo') if fork.nil?
would be even simpler. I've used it many times for things like backing up multiple directories at once, etc.)
Colin's suggestion of EventMachine would also work and would be as fast as you could possibly get if you implemented it right (and if your workflow made sense for evented async I/O), but would be far more complex and fiddly. Since you aren't trying to scale out to the entire universe, you just want to get some local utility tasks done, I think threads will do you fine and will make for simpler, more readable and maintainable code.