Image of the glider from the Game of Life by John Conway
Skip to content

A Couple Bash Goodies

Lately, I have been rewriting C-shell (csh) aliases to Bash scripts. Unfortunately, this is no easy task. Just about each alias uses conditional statements, variables and functions and range between 40-1000+ words. Each alias is also written on one line! As such, trying to decrypt the alias into something useful is very difficult. So, thus began the project to type it into a clear easy-to-read Bash function, with tab indenting, comments and the works.

Goodie #1 Listing directories and counting
Fortunately, most aliases use a certain logic flow, and and such, can be rewritten by hand with very little effort. For example, suppose I have a directory structure in the form /year/project/ where year is the 4-digits of the current year, and project represents a 4-digit project number during that year. So, a valid path could be /2005/0125/ where 2005 is the year, and 0125 is the project number. Also say, that under the project directory there by default a demo/ directory. New demo directories can be populated in the project directory as follows: demo2/, demo3/, demo4/, etc. with each number incrementing chronologically. Finally, now we need a function that copies the contents of the most recent demo directory (demo4/ in this example) into our project directory (0125). How do you write such a function?

Well, for me, I approached it as follows: I needed a listing of demo*/ directories only, then a count of the output. I assign the number of the output to a variable, say "demo_dir", then copy the contents from there. The tricky part for me was listing the directories only. I accomplished it by this:

ls -d demo*/

Worked like a charm, but now I need to get a count of those directories and assign them to a variable. This was done with 'wc' piped with 'ls':

ls -d demo*/ | wc -w

Sweet. Now I have my number, which I can assign to my variable "demo_dir". Copying from that directory is now easy:

cp demo${demo_dir}/* .

Cool.

Goodie #2 Taking advantage of arguments and date
Going back to my hypothetical scenario and directory structure /year/project/, it would probably make sense to write a function and pass a couple arguments that would take me to a directory that i specified, rather than always typing the full path of where I want to go. Let's start with looking at command line arguments first.

When typing a command, everything afterwords can be considered an argument. The arguments are in the form command $1 $2 $3 ... and so on. You can pass pretty much anything you want as an argument, be it flags, numbers, letters, punctuation, etc. So in this case, let's pass 2 arguments at most. The first being the project we want to go to and we'll make it required, and the second being the year we want to go being optional. We'll create the command gop ('go project') for this purpose. So, gop 0126 would take us to /2006/0126/ and gop 0126 2005 would take us to /2005/0126/.

So we see how command line arguments work, but in this example, if only one argument is given, then I want to utilize the current year. How do I do this? Easy, with the 'date' command. 'date' is actually very useful, even beyond my hypothetical example. Doing a man date in the terminal will yield up a ton of options. For this exercise, I just need the current 4-digit year. This is accomplished through '%Y'. Let's take a look:

if [[ $# == 0 ]]; then
	echo "ERROR: Please supply project number and/or project year"
	echo "Required usage: gop 0536"
	echo "Optional usage: gop 0536 2005 (project number and year)"
elif [[ $# == 1 ]]; then
	project="$1"
	proj_year=$(date +%Y)
	cd /${proj_year}/${project}/
elif [[ $# == 2 ]]; then
	project="$1"
	proj_year="$2"
	cd /${proj_year}/${project}/
fi

First, I do a little error checking to make sure that arguments exists. If they don't, print an error message, if they do, then continue. As you can see in the example, if only one argument exists, they I set the project year to the current year using the 4-digit format (2005). This is done by assigning proj_year $(date +%Y). If two arguments exist, then I use the second as the year, and go there. Of course, further error checking could be utilized, but because I am just changing directories, if the arguments passed are bad, then Bash itself will display an error saying the specified directory does not exist.

These are simple scripts that utilize commands we are already familiar with. However, it seems to be the simple things that get looked over the most. I just hope that you find them useful.

Post a Comment

Your email is never published nor shared.