Suppose you have some process that produces output to both stdout and stderr, like curl, for example, and you need to be able to parse both streams simultaneously.
Normally this is a pain with bash. Bash doesn’t have the handy ‘|&’ redirection that the c shells have. You can still accomplish your task, but it won’t be pretty:
res=$((((curl -sLv -X GET http://ubergibson.com \
|sed 's/^/OUT /' && echo) 3>&2 2>&1 1>&3) \
|sed 's/^/ERR /' && echo) 2>&1)
Basically what is going on here is this: the first layer of parentheses runs curl, processing stdout with sed to prepend ‘OUT ‘ to each line of output. Then stderr and stdout file descriptors are swapped, which allows us to pipe the old stderr (new stdout) to the second sed process, which prepends ‘ERR ‘ to each line.
Finally, stderr is duped to stdout and the whole mess is stored in the ‘res’ variable. Extracting the stderr and stdout from this variable is straightforward and left as an exercise to the reader ;)
Comment [6]
The 37Signals application Campfire is web-based chat app. Before today, the only way to log into a Campfire room was through a web-browser, or by using Tinder, an unofficial but sanctioned API in Ruby.
Over the past few days I’ve hacked together a Java API, based on HtmlUnit, that provides methods for logging into Campfire with a bot, or with another client that uses the API. My first project was a command-line client:
[ alan@shitfit ~/git/campfireclient ] $
./campfirc
-u alan@ubergibson.com -p password34 -s
fancypants -S
Using SSL.
Now connected to "fancypants.campfirenow.com"
Available commands:
/join <room>
/quit
/join Bots
Now chatting in "Bots"
whats up dudes?
Robot M.: whats up dudes?
Alan D.: we chill
Anyways it rules, and I’ve posted it over at github.
Comment [69]
A continual pain when dealing with Java software is managing the CLASSPATH environment variable. I’m dealing with HtmlUnit, which depends on 12 jars. You can include everything in a big jar file if you’re deft enough with Ant, but a lot of projects – to include my personal ones – depend simply on a colon-delimited CLASSPATH of jars.
So here’s a little ditty that, fed a directory, does some magic with find(1) and searches the directory for any jar file, appending it to CLASSPATH. Behold:
MYJARS=/Users/alan/jars
export CLASSPATH=$CLASSPATH$(find $MYJARS
-name *.jar -exec printf :{} ';')
You can get fancy with find’s options if you want; there’s a shitload of them and the sky is the limit. I use printf(1) instead of echo(1), because it reliably prints its input sans-newline across most platforms.
Comment [4]
So part of anyone’s programming process is commenting and un-commenting blocks or lines of code. To comment and un-comment with “//” style comments in Vim using ./ and .? as your hot keys, respectively, put this in your ~/.vimrc:
map ./ :s/^\(\s*\)/\1\/\//<CR>
map .? :s/^\(\s*\)\/\//\1/<CR>
type ./ to comment
type .? to uncomment
“//” style comments cover C99, C++, PHP, Java, and a variety of other languages with C-like syntax.
The (\s*\) bit captures any whitespace at the beginning of the line, so your tab formatting doesn’t get messed up.
Remember, once you’ve made a selection in visual mode, you can always type “gv” to make the selection again.
One more thing: to quickly select an entire line in Vim, Shift+V. You can comment and uncomment individual lines in a flash with vim. Optimal.
Vim rules.
Comment [592]
Suppose you have a directory of files, and all of the files have a common prefix that is a certain number of characters long, and you want to take the prefix off. Your directory looks like this:
[alan@shitfit testdir]$ ls
000-lol.zip 001-rofl.txt 002-roflmfao.jpg
So to get rid of the numbers and dashes in all of the files, you can do something like this:
for F in *; do mv $F ${F:4}; done
The ${F:4} bit tells Bash to print the string $F starting at the 4th character. It turns out Bash does all kinds of things with strings, as you can see here.
So, your result will look like this:
[alan@shitfit testdir]$ ls
lol.txt rofl.txt roflmfao.jpg
To tune your renaming to a certain file extension, you might use:
for F in *.txt; do mv $F ${F:4}; done
You have a number of options available, and all of them involve a loop, some kind of formatting approach, and the mv command. Micha suggested using find and piping the results to while, read, sed, and mv. This guy does something like that to match the beginnings of filenames to a pattern.
Presto.
Comment [7]