Making unix programs

It is really easy to add your own commands to Unix. Even a small script you write can be used in the same way as other unix commands. (Which is actually the reason Unix is a mess sometimes, because everybody went in and added their own commands.)

The reason it is so straightforward to create Unix programs is that you do not have to program or design a graphic user interface: everything runs from the terminal. This is part of programmer culture: like glit argues, if you want to stay up to date with new exciting developments, you need to know how to run things from the terminal, because programmers are usually not going to take the time to create a graphical user interface for their latest experiments. Instead, they, will distribute it as a unix script.

The interface

Instead of letting the user manipulate buttons and text boxes, a unix program accepts arguments and options on the command line. Unix programs can also specify what to do with the text passed in by other programs via pipelines (standard input). And what almost every program does: they can output text to the terminal (standard output).

6 Comments

Unix has been conceived in a modular fashion: even the most basic unix commands are really simple unix programs, that exist indecent of the other commands. For example, if you run:

which cd

You will find that cd is a program that lives in /usr/bin/cd.

Because of the modular nature and straightforward interface, it is easy to add commands to Unix with even the most basic of programming tools. This is Unix strength and it’s weakness. Unix has been able to grow organically, with different people adding different commands over time. This has made it versatile and comprehensive. Simultaneously, Unix is hugely inconsistent in naming commands, and commands often behave differently from each other in hard to predict ways. Also, newcomers are faced with the ballast of history: the name of the less program, that lets you page through the contents of a file, only makes sense if you know that its predecessor was called more.

But as a an example, to turn the series of commands from our previous post first into a script and then into a unix command, this is what we do. First we make a file called jenny.sh with the following contents:

#!/usr/bin/bash
curl "http://twitter.com/statuses/user_timeline/jennyholzer.json?count=1" | sed 's/.*"text":"\(.*\)"}]/\1/g' > jennytweet-tmp.txt
pango-view -q -o jennytweet-laidout-tmp.ps --font "Futura 36" -w 400 jennytweet.txt
poster -s 4.4 jennytweet-laidout-tmp.ps
# remove temporary files:
rm jennytweet-tmp.txt jennytweet-laidout-tmp.ps

This will print out the postscript of the resulting poster to the output, and then remove the needed intermediate files (the rm command removes files€you should take care with this one!). We can run it with the shell program, that interprets shell commands:

sh jenny.sh

(Of course, in most cases you would want to redirect the output to a postscript file:

sh jenny.sh > jennytodayposter.ps
.)

We can also make script executable, that is we give it the rights to be a program

chmod +x jenny.sh

Actually, we don’t need the .sh extension: the script starts with #!/bin/bash which is there to let the shell understand that the script should be run by the shell. Python scripts that you want to run should similarly start with #!/usr/bin/env python, to let them be run by the python interpreter. Lets rename:

mv jenny.sh jenny

Now we can run the script directly:

./jenny

Notice that we need to specify that the program is located in the current folder (./). When running programs, unix behaves a little different than with other files. It doesn’t automatically look in the current folder for the program, like it does for documents. Since the unix system commands themselves are programs stored on your computer, if unix would automatically use the programs in the current folder, it would be very easy to override default programs such as cd and pwd and ls, messing in this way with the expected behavior of the system.

Rather, when you don’t specify the location of the program, unix looks in a number of pre-specified locations, like the /usr/bin folder where we found our cd command, or the /usr/local/bin folder where Homebrew places programs. If you want to turn your script into a command accessible from any folder, you should put it in such a folder:

mv jenny /usr/local/bin

We can now run the script from anywhere simply as

jenny

And just like that, you have added a command to Unix. In practice to write little scripts and programs that work in the terminal, using scripts with shell commands is not always the easiest. Most of the time it is more straightforward to use a general purpose programming language like Python. That is what bnf uses for, for example, his vector pixels script.

Alternatively you could just keep the script local and add it as a command by adding an alias statement to your .bashrc such as: alias jenny /home/erik/tools/jenny.sh This way you don't accidentally forget to backup your diy tools when you reinstall your system or even need brew to create user writable bin paths.

If you don’t want to add aliases for each script, you can also add your own folder to the path, the list of folders unix searches for executables. Instead of a file called .bashrc, I use a file called .profile. I put this in my home folder. I add to it the line:

export PATH=~/bin:$PATH

I make a folder called bin inside my home folder, and all the scripts I put in here are automatically recognised. The first time you do this, you may need to run:

source ~/.profile

Afterwards, it will load automatically when you login.

Reply

Leave a comment