Thursday, February 08, 2007

A scripting tip for the nerds

I don't know how many of my nerd friends read tihs, but if you're not one of them you can pretty much just skip this post.

I love writing bash scripts. I run cygwin on windows, so I have the ability there too. One of my common tasks in bash is a task such as "For all the files in this directory that match some pattern, do this to them".

Previously my script would have been in the form:


for x in `find . -name '*pattern*' | sed -e s'/ /@/g'`; do
realname=`echo $x | sed -e 's/@/ /g'`
dostuffto $realname
done

Notice how I had to use sed to replace spaces with some character, and then unreplace it? That's cuz "for" uses space delimited input, and if there's a space in a filename it screws up.

Last night I accidentally discovered this. It works better in some cases, not as well in others:
for x in *; do
dostuff $x
done

As it turns out, file wildcards (*) automatically escape spaces and other weird characters, whereas ls does not. I even tried ls -b (which adds escape characters), to no avail. Of course, '*' isn't as flexible for finding files as 'find' is, but for smaller scale searches this kicks ass.

Update:

I finally figured out how to use the -exec option to find, which also fits into this problem.
Here's how to use find to execute commands on the files:
find . -name 'whatever' -exec ls -l '{}' \;

The file is substituted in for {}, and the '' around that takes care of spaces. the \; at the end marks the end of the command to execute.