Tuesday, November 1, 2011

Scripting fun with Automator

Ok, I'll be the first to say that scripting and command line operations are not the first thing that I learned to like on computers, but a lot of times they really can save a lot of time or... destroy files at random on a disk (rsync with a few not too correct paths and parameters here and there) ;).

As GUI only tools cannot always do the best job possible on their own or do not have certain capabilities by default, scripting in the command line can have its fair share of drawbacks... most of the time, an efficient workflow will consist of making it possible to quickly open a GUI file explorer from the command line and open a command line terminal from a specified folder in the GUI file explorer.
Sometimes, what I really want to do with scripting on a MacOS X system is to extend the Finder, making a small Finder Service that allows me to quickly do operations on files and folders as if the Finder could natively do it on its own. Call it create an normal PNG from an iPhone retina resource (say with a -hd suffix for those of you using Cocos2D) or a batch of them, call it generate a PVR texture using PowerVR's tools, call it delete all header files (.h) or all non-header files (*.c, *.cpp, *.m, *.mm, etc...) from a folder or a whole hierarchy of folders, etc... Sometimes Apple's Automator actions are enough on their own or it is simply easier to do it with Automator actions chained together, but sometimes what you really want to do is for Automator to let you link a folder, set of folders, or files to a shell script.
The problem with that strategy is the concept of working directory for the script and the target folder you would like that script to work inside of.

One way consists in getting from finder a set of files in one folder and its sub-folders and perform a batch action on them, say doing a simple scaling of a PNG using ImageMagick's tools, the script we can use inside Automator's Run Shell Script node (which would follow a Filter Finder Items node in which you can filter out the non .png files) could be:

for f in "$@"
do
    cd $(dirname "$f")
    /opt/local/bin/mogrify -resize 50% "$f"
done

A little bit of advice would be to alwas select the "pass input as arguments" option in the Run Shell Script node, for the above script to do what it is supposed to do. "$@" is a special keyword that basically includes a list of arguments to the current scripting node in Automator.
The following command

cd $(dirname "$f")

changes the working directory to the directory in which the provided file is located in.

In some cases that trick is enough, in others you just want to port your existing shell script so that it is able to run inside the folder you have selected in Finder in the simplest way possible (this is the meat of this post... or rather what motivated me to post this item tonight).

The Automator's Service workflow you are going to create is even simpler here:

1.) Service is configured to receive selected folders in Finder (top of the window).
2.) The Run Shell Script is configured to pass input as arguments.
3.) This is the code you write in the script src section (in this case I wanted to convert a bunch of .wav files into .mp3):

automatorInputFolder="$1"
export automatorInputFolder
/opt/local/bin/custom/convertWav2MP3.sh

The magic here is the "$1" element which we save in a shell variable we export in the script so that other scripts launched in this step can use. "$1" is the currently selected folder in Finder.
This is the script in question (using the lame-encoder-related script-fu found here: http://www.discogs.com/groups/topic/151711):

#!/bin/bash

#echo "$automatorInputFolder"
#echo "$(pwd)"
cd "$automatorInputFolder"
#echo "$(pwd)"
for i in *.wav; do /opt/local/bin/lame -b 128 -h "${i}" "${i}.mp3"; done
find . -name "*.wav" -exec rm -f "{}" \;
ls *.wav.mp3 | sed 's/\(.*\)\.wav\.mp3/mv "\1.wav.mp3" "\1.mp3"/'|sh


(you can still see some debug echo commands there... Automator allows you to run the actions inside the app using a pre-defined input and see the output of all commands like the echo one... very useful :))

After this step in the above script

cd "$automatorInputFolder"

the script can execute with the correct working directory, the folder you have selected in the Finder.

I hope this can be helpful to you too :)!

No comments:

Post a Comment

Related Posts Plugin for WordPress, Blogger...