Monday, November 29, 2010

Just getting the current directory from command line

A request from a co-worker turned out to be more complicated than I though. He just wanted the current root directory, not the full path, to be returned.

Turns out BASH doesn't provide this functionality directly to you, but does provide tools to enable your own solution. We'll use PWD to nab the full directory path, and then find a way to extract the last returned directory. So the cast:
  • PWD - returns the working directory name in a full path
  • CUT - cut's out selected protions of each line in a file
  • python - to reveres a string. You can switch this element out with ruby or any other preferred method.
The Command:

pwd | python -c "print raw_input()[::-1]" | cut -d'/' -f 1 | python -c "print raw_input()[::-1]"

Under the Hood:
PWD prints out the full path. Then we use Python to reverse the string. Putting our last directory first. Next we use CUT to define the path as a list. Where the delimiter breaks it down into separate fields by '/'. We then specify we want the first field returned, which is secretly the last directory that has been reversed. Finally we re-reverse the returned string back to it's original state.
  1. pwd: /Users/tspangle/Documents/projects
  2. python: stcejorp/stnemucoD/elgnapst/sresU/
  3. cut: stcejorp
  4. python: projects









Monday, September 27, 2010

Another reason to learn bash scripting.

Initially I was not a fan of the Mac. Even after working on Snow Leopard during a three month internship. However my latest employer has made a good impression for Macs by showing me that Terminal is not dead. After all the problems I encountered with SVN in the various gui's I was ordered to use the command line and have loved it ever since.

One reason is the amount of time and keystrokes saved by using bash scripting. Here's a snippet of a few current functions:

#Opens the differences in vim for an easy snapshot of what's changed
svndiff()
{
svn diff "$(@)" | view -
}

#Marks all ? files to be added in the next commit.
svnaddr() {
svn status | awk '/\?/{print $2}' | xargs svn add
}

But the reason for this post is another benefit I found to bash scripting. One hurdle in working with my co-workers is expecting them to commit their css and html modifications to a git repository in a Putty session. This requires them to do many things they haven't learned and generally are not excited about doing anyways. It will most likely result in a poorly managed project, thus making it more difficult to work in git with their modifications.

The designer's process is to work on the application through sftp. Then they're expected to fire up Putty, login, navigate to the web directory and perform the needed git commands. I don't think it's a healthy level of expectation for someone who isn't technical to jump into something like that and do it well. My solution was to create a series of functions that will translate terminal and git syntax into a more intuitive process. So the process has now been boiled down into three requirements:
  • Knowing how to login through Putty
  • Knowing your own name
  • Being familiar with the tab key
After the designer logs into Putty they just need to type their name and double-tab to list the possible completions:
dude_show_modified_files
dude_commit
dude_is_done_for_the_day

There are others but that's the basics. Function _show_modified_files provides a number, and a file name:
files that have been modified:
(7) app/public/common/stylesheets/search.css
(8) app/public/common/stylesheets/generic.css
(9) app/views/search/_result.html.erb

next the _commit function is called with the # and a short commit message. If you forget either of these parameters you get a friendly reminder:
you must provide a numerical value along with a message from _show_modified_files i.e. commit 9 "changed search box layout"
files that have been modified:
(7) app/public/common/stylesheets/search.css
(8) app/public/common/stylesheets/generic.css
(9) app/views/search/_result.html.erb

Making the process more intuitive to the user helps ensure they will do it right and as expected. Another nice thing about this is that the scripts are customizable to the user. So in the commit statements I can include the --author options and we can blame the right person. Opposed to them copying my examples and defaulting to the configured users.

dude_show_modified_files()
{
cd ~/webapp
echo "files that have been modified:"
git status | awk '/modified/ {print "("NR") " $3}'
}

dude_commit()
{
if [[ ! ("$#" == 2) ]];then
echo 'you must provide a numerical value along with a message from _show_modified_files i.e. commit 9 "changed search box layout"'
dude_show_modified_files()
return 0
fi
cd ~/webapp
git status | awk -v line="$2" '{if ( NR == line) print $3}' | xargs git commit -m"$1" --author="Dude Tester "

}