Create another version of the Unix cal command

There are many ways to see date and calendar information in OS X. There’s the full-blown iCal, of course, for managing your work and personal schedules. There’s also the simple menu bar clock, which will tell you the time and display the date when clicked.

If that’s not enough, though, there are numerous third-party programs that also work with calendars—everything from full-blown iCal replacements such as Now Up to Date to simpler utilities, such as MenuCalendarClock for iCal, which we looked at back in 2005, and again more recently in this Macworld video.)

If you use Terminal, though, you’re probably familiar with another method of working with date and calendar information—the Unix cal program. If you type cal in Terminal (in Applications -> Utilities) and press Return, you’ll get a handy little printout of the current month:

$ cal
      May 2008
Su Mo Tu We Th Fr Sa
             1  2  3
 4  5  6  7  8  9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31

You can also print out full year calendars for any year by using the -y option: cal -y 2009 will print out a full calendar for next year. If you read the man page for cal, there seem to be some additional options, including one (-w) that will display the week numbers along with the current month. However, if you try to use it with cal, here’s what you’ll see:

$ cal -w
usage: cal [-jy] [[month] year]
       cal [-j] [-m month] [year]
       ncal [-Jjpwy] [-s country_code] [[month] year]
       ncal [-Jeo] [year]

Despite this option being listed in the cal help file, it doesn’t seem to work. But there’s a clue in the above message; it shows the -w option being used with a program named ncal, not cal. So you try it:

$ ncal -w
-bash: ncal: command not found

So much for that approach—it seems the ncal command isn’t installed. That’s not quite correct, though—it is installed, but the system doesn’t yet know about it. You see, ncal is really just cal but with some different options. They’re the exact same program, but OS X doesn’t know that yet. We’re going to solve that problem by creating a symbolic link (something like an alias in the Finder) that “creates” ncal by connecting it to the existing cal executable. Please note that this hint will only work in OS X 10.5.

(You may be wondering just why a program will run with different features when it’s called with a different name, even though the actual code being run is exactly the same. Apparently this is a result of similar but separate Unix programs merging into one program over time. Way back when, cal and ncal were separate programs. However, since they did very similar things, they were merged into one code base at some point in time. If ncal were to have completely vanished at this point, anyone who used it in scripts would have to go back and modify all their scripts to refer to cal instead of ncal.

To avoid breaking scripts, the merged ical/ncal program behaves differently depending on which name is used to activate it. Thanks to this feature, people with scripts that used ncal didn’t have to modify their code, they just needed to create the ncal symbolic link, and all their scripts would keep working. Apparently this is somewhat common in Unix, but it really struck me as strange when I first ran into it.)

To make it easy to run our “new” ncal program, we’ll create it in the /usr/local/bin directory, which is a directory that OS X knows about (i.e. it’s a known location for executable files), so you can execute programs within it from anywhere in Terminal. Even though OS X knows about this directory, it may not exist on your machine. If you’re not sure it exists, try typing cd /usr/local/bin and pressing Return. If you see an error message about No such file or directory, you know you need to create the directory. To do so, just type sudo mkdir /usr/local/bin and press Return. You’ll be prompted for your administrative password; enter it when asked, and the directory will be created.

Now that the directory is created, we can create our new ncal program. To do that, we’ll use the ln command, which links one program to another. In this case, we want to link the original cal to a newly-created ncal file, using a symbolic link. (There are two types of links in Unix, symbolic links and hard links. Creating a symbolic link is very much like making an alias in the Finder; creating a hard link is more like duplicating a program in the Finder.) To do that, type this command:

sudo ln -s /usr/bin/cal /usr/local/bin/ncal

(If you’d like to remove ncal at some point in the future, just type sudo rm /usr/local/bin/ncal, press Return, and provide your password when asked.)

To check that the command worked, print the contents of the /usr/local/bin directory using the -l option—just type ls -l /usr/local/bin. You should see something like this:

$ ls -l /usr/local/bin
total 8
lrwxr-xr-x  1 root  wheel  12 May 23 06:39 ncal -> /usr/bin/cal

As you can see, ncal is listed there, with an arrow pointing to the linked original cal program. To test your “new” program, type ncal -w, and you should get a printout of the current month with week numbers:

$ ncal -w
    May 2008
Mo     5 12 19 26
Tu     6 13 20 27
We     7 14 21 28
Th  1  8 15 22 29
Fr  2  9 16 23 30
Sa  3 10 17 24 31
Su  4 11 18 25
   18 19 20 21 22

The last line in the output is the number of the above week in the current year. By “installing” ncal, you also gain a couple of other options. ncal -e [year] will display the date for Easter for western churches in the specified year—if you leave off the year, the current year is assumed. If you use the -o option, you’ll get the date for Easter for Greek and Russian Orthodox churches. Finally, if you’d like to see the current month in the Julian calendar, just type ncal -J.

Subscribe to the MacWeek Newsletter

Comments