New command: prepend
April 6th, 2008
I am utilizing Google’s project hosting to host software which I create and feel is useful or want to keep track of. I called the project Brock’s Tools. The code that led me to create this project was a command I am calling prepend 1.1. (UPDATE: See this post on sponge as its a better general case tool.)
prepend, prepend’s files or standard input to a file. For example, you have three files:
$ echo BROCK > a $ echo DAVID > b $ echo NOLAND > c
And you want to combine them into one file:
$ echo "My name is:" | prepend - a b c $ cat c My name is: BROCK DAVID NOLAND
Or lets say you just want to append a file to itself:
$ cat a BROCK $ cat a >> a cat: a: input file is output file
prepend does this:
$ prepend a $ cat a BROCK BROCK
I come across the a situation where this would be useful quite often. Of course prepend’ing can be done in the shell:
$ { echo "My name is:"; cat a b c; } > tmp && mv -f tmp c
$ cat c
My name is:
BROCK
DAVID
NOLAND
However, that is unsafe and I have lost data that way. I perform this operation most often when dealing with XML. In this example, its trivial to open the file in an editor, but with a large file, its quite nasty to do so:
$ cat something.xml <entry><blah/><more>stuff 1</more></entry> <entry><blah/><more>stuff 2</more></entry> <entry><blah/><more>stuff 3 </more></entry> <entry><blah/><more>stuff 4</more></entry> $ echo "</entries>" >> something.xml $ cat something.xml <entry><blah/><more>stuff 1</more></entry> <entry><blah/><more>stuff 2</more></entry> <entry><blah/><more>stuff 3 </more></entry> <entry><blah/><more>stuff 4</more></entry> </entries> $ echo "<entries>" | prepend - something.xml $ cat something.xml <entries> <entry><blah/><more>stuff 1</more></entry> <entry><blah/><more>stuff 2</more></entry> <entry><blah/><more>stuff 3 </more></entry> <entry><blah/><more>stuff 4</more></entry> </entries>
Wrapping dynamic languages in shell without an extra script
March 25th, 2008
There are situations where, if you want a Python, PERL, PHP, etc script to be portable among a few different servers, it makes sense to wrap the script in shell. A few years ago I was trying to use the Python cx_Oracle module. This module is a wrapper for the native Oracle database driver. However, it requires the driver library directory be in the LD_LIBRARY_PATH environment variable.
No problem I thought. I’ll use the os.environ dict to set the variable. Example script:
$ cat python-only.sh
#!/usr/bin/python
import sys, os
sys.path.append("/usr/local/lib/python2.4/site-packages/")
if not os.environ.has_key('LD_LIBRARY_PATH'):
os.environ['LD_LIBRARY_PATH'] = "/home/noland/oracle-lib"
else:
os.environ['LD_LIBRARY_PATH'] = "/home/noland/oracle-lib:" + os.environ['LD_LIBRARY_PATH']
print "LD_LIBRARY_PATH looks OK in Python: LD_LIBRARY_PATH = ", os.environ['LD_LIBRARY_PATH']
os.system('echo LD_LIBRARY_PATH looks OK via os.system: LD_LIBRARY_PATH = $LD_LIBRARY_PATH')
try:
import cx_Oracle
print "Imported cx_Oracle! LD_LIBRARY_PATH was set correctly."
except ImportError, e:
print "Woops, LD_LIBRARY_PATH was not set correctly: ", e
This method does not work:
$ ./python-only.sh LD_LIBRARY_PATH looks OK in Python: LD_LIBRARY_PATH = /home/noland/oracle-lib LD_LIBRARY_PATH looks OK via os.system: LD_LIBRARY_PATH = /home/noland/oracle-lib Woops, LD_LIBRARY_PATH was not set correctly: libclntsh.so.10.1: cannot open shared object file: No such file or directory
This seems to be a common problem. However, when I was dealing with this a few years ago, I could not find a good resource on Google. I bite the bullet and wrote a separate shell script wrapper – hating invocation of the shell script. However, there is absolutely no reason I needed a separate shell script. I could have embedded the Python within a shell script. Example:
$ cat python-and-bash.sh
#/bin/bash
export LD_LIBRARY_PATH=/home/noland/oracle-lib:$LD_LIBRARY_PATH
/usr/bin/python<<END_OF_PYTHON
import sys
sys.path.append("/usr/local/lib/python2.4/site-packages/")
try:
import cx_Oracle
print "Imported cx_Oracle! LD_LIBRARY_PATH was set correctly."
except ImportError, e:
print "Woops, LD_LIBRARY_PATH was not set correctly: ", e
END_OF_PYTHON
Ahh, much better:
$ ./python-and-bash.sh Imported cx_Oracle! LD_LIBRARY_PATH was set correctly.
Of course I could have just set this variable in my profile. However, this creates an additional external dependency – which is what I was trying to avoid.