Wednesday, December 28, 2011

a piece of py: renaming files

I hate spaces in the names of files. It's a quirk of my personality. I prefer CamelCase as an alternative. I used to like a mix of lower case letters, hyphens and underscores, but that was before my world of Unix and Python was dominated by Java.

However, I am a member of the minority and so I often end up with folders and files whose names aspire to be sentences (or at least parts of speech like nouns, prepositions, pronouns and the occasional verb [To be DELETED: ugh!). Today was one of those days. I had a folder full of PDFs, each with a name of the form Last, First.pdf. I would have preferred a name like FirstLast.pdf. The easiest way to do this was with some shell-fu or Python-fu (with due apologies to the GIMP). I tossed a coin and chose Python. I fired up PythonWin and started working on fragments that would eventually unite into a single one-liner to rename them all (sorry JRR). I wasn't smart enough to reduce it all to one line (I needed the imports and I was not a lambda knight).

import fnmatch, os
# basedir is a string representing the full path to the folder
# containing the poor PDFs
for pdf in fnmatch.filter(os.listdir(basedir), '*.pdf'):
  new_name = ".".join(["".join(reversed(pdf.split('.')[0].split(', '))), 
                      pdf.split('.')[1]])
  os.rename(os.path.join(basedir, pdf), os.path.join(basedir, new_name))

Of cours,e I could have skipped using new_name completely:

import fnmatch, os
# basedir is a string representing the full path to the folder
# containing the poor PDFs
for pdf in fnmatch.filter(os.listdir(basedir), '*.pdf'):
  os.rename(os.path.join(basedir, pdf), 
         os.path.join(basedir, 
                 ".".join(["".join(reversed(pdf.split('.')[0].split(', '))), 
                 pdf.split('.')[1]])))

I think this might be the first time I used reversed(), but since it was a relatively recent addition (2.4 to be precise), I didn't feel too bad. Had I written this code before 2.4 had been released, I would have been forced to use reverse(): this also reversed the list, but did it in place and did not return the list; I would be forced to reverse the list first and then send it onto the join conveyor belt.

I also like how just adding brackets as bookends to items separated by commas, I get a list:

["".join(reversed(pdf.split('.')[0].split(', '))), pdf.split('.')[1]]

Mission accomplished. With some learning to boot. Not bad for a few minutes of work.

Monday, December 26, 2011

pentahexed: the tale of a misleading manifest

If you have worked with Oracle's JDBC drivers before, you are no doubt familiar with ojdbc5.jar and ojdbc6.jar.

Oracle tells you that ojdbc5.jar contains Classes for use with JDK 1.5. It contains the JDBC driver classes, except classes for NLS support in Oracle Object and Collection types and that ojdbc6.jar contains Classes for use with JDK 1.6. It contains the JDBC driver classes except classes for NLS support in Oracle Object and Collection types.

Take a class oracle/core/lmx/CoreException.class from each JAR, send it to file and you are not surprised with what you see:

(for oracle/core/lmx/CoreException.class from ojdbc5.jar): compiled Java class data, version 49.0 (Java 1.5)
(for oracle/core/lmx/CoreException.class from ojdbc6.jar): compiled Java class data, version 50.0 (Java 1.6)

Open the manifest of each JAR, however, and you see something interesting. The value of Created-By is the same in both JARs: 1.5.0_30-b03 (Sun Microsystems Inc.). How can a JDK 1.5 compiler know about JDK 1.6? Surely, this has to be something lurking in the scripts that needs to be fixed. It also wouldn't hurt to use a newer version of Ant (the value of Ant-Version) is Apache Ant 1.6.5 (the latest version is 1.8.2).

 
Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License.