Making Your Programs Executable - automated?
Introduction
Last entry I introduced a method for creating Perl or Shell Script executables. There may be better ways, but that one works for me. As a linguist I am constantly writing scripts to accomplish a variety of tasks. Tracking all the scripts can be a chore in its own right.
I decided (part of my on-going 20 year campaign to stay organized) that I need a script that would take care of not only creating the executables, but one that would archive the source code. That way I knew where to find the code should I want to return to it later.
Of course there's a bit of a trick here (I later learned) and that is that just because the attributes of a file are set to executable doesn't prevent you from opening it up and making changes to it! Pretty cool, unless of course you screw something up, but I have cut this corner a few times.
The second objective in this project was to re-familiarize myself with the Unix shell. While my earliest days as a computer geek were spent in an industrial Unix environment, I have spent enough time away from it to forget a lot of things. For cross platform compatibility I selected Perl as my main scripting language, but the power of the Unix shell cannot be ignored for too long, especially if you're concerned with productivity.
Scripting Basics
There are many reasons why anyone would want to learn any scripting language. If you want to see a list, check out this site:
This site is a full tutorial on bash scripting and will introduce you to most of the features you will need to write basic shell scripts.1
One Big Command Line
I like to think of a shell script as just one big collection of command lines. Since many tasks (such as our building and executable file) requires several steps from the command line, it is good candidate for a script.
From a command line (shell prompt) perspective our executable is built by the following instructions:
Example 1.
At the minimum we have three instructions to accomplish our task. On the other hand we also have to remember 2 commands: chmod (change modes) & cp (copy); 2 pieces of key information: 755 (the code needed by chmod to make our program executable) and of course the program name; and 2 path names. (This is manageable, but I sometimes forget things such as the 755).
A Most Simple Script
In the previous installment Making Your Programs Executable, I introduced you a very basic hello.sh script. Aside from the excitement of saying "Hello" to yourself (everyone ever writing a program has done this one) the most important part of that simple little script is the magic "she-bang" line: #!/bin/sh . You may have noticed this is very similar to the Perl counterpart: #!/bin/Perl .
The she-bang line is required in any script. It tells the shell which program to use in executing it. The bin/sh tells Unix to use the bash shell in the bin directory and the bin/Perl tells Unix to find and use the Perl module in the bin directory. The magic here is that this line determines the program type, not the file extension itself as on a PeeCee.
Let's create a basic shell script to make our executable "instruction list".
Example 2.
Remember to save it using Unix linefeeds if you have an editor that allows options for different formats. Without the Unix linefeeds your script will generate an error.
If you execute the script in example 2. It will do the same thing as the 3 commands did in Example 1. only you type one command: sh my_shell_script.sh. The catch is that it only works on the program_name.sh file!
Passing Parameters
The ability to pass parameters to any script is part of the power. That allows us to create a single script that can operate on multiple files. In this case we like the idea of "automating" the process of creating and archiving our executable script, but we want to be able to use the tool to operate on any file we chose without rewriting any code.
The simplicity for passing parameters to a shell script is in many ways easier than many other scripting languages.
Example 3.
Notice that the only change required to allow the parameter passing was to change each occurrence of the filename to $1. That's it! Pretty cool if you ask me. The bash shell automatically keeps track of any parameters used and stores them in the variables $1, $2, etc. All we need to do is use them.
Off course with the added convenience of parameter passing comes added responsibility. Now that our script expects to see a parameter, we have to make sure that we account for the possibility (or error) of not getting the required parameter. This error trapping is easily accomplished and illustrated in the following expanded version of our script.
Example 4.
In line 3 we set a variable MINPARAMS=1. The number of arguments/parameters passed to the script are stored in the $# variable. If $# is less than $MINPARAMS (line 5) then we will print an error message (lines 8,9) then exit (line 11). Should the number of parameters be equal to (or greater than) $MINPARAMS then we execute the 3 commands form our previous script.
Final Touches
I'll wrap this up by showing my final makemyexe.sh script.
Example 5.
You'll notice I added a few additional features. The script can now accept 2 parameters, one for the file to be made executable and a second for changing the name. I haven't tested this extensively. My renaming of files involves the removal of the .sh or .pl. I recall that radical renaming was problematic. I have not tested the scripts behavior with more than 2 parameters. As it is, it serves my proposes well and perhaps serves to show some of the power/benefits of the shell scripts.
If you have comments or feed back let me know. Otherwise, enjoy.