Bash manipulation on sequences.

I’m going to come at you today with a very common situation. Renaming a series of files, bash and GNU utils style. This applies to something as trivial as importing my camera photos which typically gives me a bunch of files named IMG_2042.JPG, IMG_2043.JPG, IMG_2044.JPG and so on. I’m here to show you how to deal with that.

We’re gonna tackle this ground up. Firstly, I need a way to increment a number. seq is our tool.

seq -f %04g 1 3
0001
0002
0003

Sexy huh? We’ve already have a major building block right here. Let’s dissect this quickly. The ‘-f’ tells seq that we want a specially formatted list of numbers. In our case, zero padded numbers, at least 4 wide (%04). The letter ‘g’ gets replaced the current number in the following range (1 thru 3 in our case). If you don’t have padded numbers you can omit the use of ‘-f %04g’ altogether. The last two arguments are the range to start and end.

seq 1 3
1
2
3

Sweet, now we have way of representing pretty much any sequence of numbers, thanks seq! Now let’s tackle looping over this sequence of numbers and use them for renaming using a simple ‘for’ loop. In our case below the letter ‘n’ will get the results of the seq command.


for n in $(seq -f %04g 2042 2044) ; do mv IMG_$n.JPG utah.$n.jpg ; done
`IMG_2042.JPG' -> `utah.2042.jpg'
`IMG_2043.JPG' -> `utah.2043.jpg'
`IMG_2044.JPG' -> `utah.2044.jpg'

That one-liner is so unbelievably flexible (replace `mv’ with `cp’ or `ln’ for instance) it will probably be your number one oft used idiom while working with bash in production. As a matter of fact, pretty much every thing I do is looping over a list of things – yum, sounds lispy.

I’ve always found this to be a great (re)read. In the beginning was the command line. It’s a zip archive, with an ol’ fashioned text file for you to read authored by Neal Stephenson.

Maya and Python and menus oh my!

Updated, was, “Multiple Python commands with Maya’s menuItem MEL”

Maya drives me nuts. I really wish I could spend my day in Houdini to see if it sucks less. Anyway, I digress. Python is awesome. Python’s integration with the rest of Maya is, well lacking.

I like to add my own ‘Pinkwerks’ menu to the main menu bar in Maya for ease of access to my favorite hacks. Turns out, you can’t add a custom menu to the main menu bar in Maya via userSetup.py as you would in userSetup.mel – It doesn’t seem to have access to the GUI when it’s evaluated during Maya’s start-up. Maybe someone can prove me wrong. So, I’m lamely forced to writing my own menu for the main menu bar with classic MEL which looks something like this.


global string $gMainWindow;
setParent $gMainWindow;
global string $gPinkwerksMenu = "Pinkwerks";
menu -label "Pinkwerks" -allowOptionBoxes true -tearOff true $gPinkwerksMenu;
menuItem -label "My Fancy Command" -command "myFancyCommand";

Now, let’s bring the pain. You’ve written a Python script and you want to call that script from a menuItem (as in the last line in the above code). A couple of points.

If you write foo.py and put it in MAYA_SCRIPT_PATH it isn’t loaded automagically like a .mel. (You’ll recall that if you name a .mel with the same name as a global function, it’s automatically callable by Maya at run-time. For instance if you have a file ‘myNoise.mel’ in a directory in the MAYA_SCRIPT_PATH environment variable and it contains a function in the form of ‘global proc myNoise(…){…’ you can type ‘myNoise’ at the MEL prompt or script editor and Maya will ‘find’ it without having to source it first.

This means if you have a Python function ‘myPyFunk’ in foo.py (and it resides in your MAYA_SCRIPT_PATH) – you still have to ‘import foo’ before you can call foo.myPyFunk(). Trouble is, this is two steps, the ‘-command’ argument to menuItem won’t evaluate a newline, even if you try and escape the hell out of it. So instead of foolishly trying this:

*BAD CODE FOLLOWS*

menuItem -label "My Py Funk"
-c "python(\"import foo\nfoo.MyPyFunk()\")";

To work around this you can structure your commands like so:
*GOOD CODE*

menuItem -label "My Py Funk"
-c "python(\"import foo\");python(\"foo.MyPyFunk()\")";

One last method of calling Python scripts before I wrap this up. If you’re like me, you tend to write code in and external editor. In Maya, for ease of use you want something analogous to `source mySheet.mel’, which reloads the file and runs the main task. You can get away one-liner simple execution of python scripts like so from the Python prompt or script editor tab:


execfile("/home/pink/maya/script/foo.py")

This trick is achieved by adding the 2 lines below to the end of your .py. This assumes you wrap the guts of your script in a function named ‘doit()’. The Python interpreter will automatically call the function ‘doit()’ when it parses this file during the execfile(). Note in this case, anything you type in the foo.py will be evaiuated with exec, so I tend to wrap everything in a function and don’t leave any `raw’ python lying about.


def doit():
sel=ls(sl=1)
for s in sel:
...

if __name__ == '__main__':
doit()

Unfortunately this process is less clean than MEL in terms of ease of integration, but not so bad once you get over the ‘gotchyas’. Personally, I’m digging PyMEL.

Easy right?

XBOX Lips : Gomez spotlight

Thought I’d show off some character designs I came up for an XBOX Lips commercial from a couple years back. I kept trying to name him ‘Gomez’, it didn’t stick and he was better known as “Lippy”. These 3D models were a study from a 2D design provided by the agency. He was a tricky guy to fit all those teeth into. The final one was produced as hybrid comp trick so that we could fit a huge mouth magically into a space smaller than the volume of his torso.

Shout outs to the ISZ and Sam Kieth!