If you type the command calendar , you'll see lines with "to-do" items for today and tomorrow from a file named calendar in your current directory. If you put that file in your home directory, your system administrator can run the command calendar -to mail ( 1.33 ) everyones' "to-do" items to them. You can also automate your personal calendar setup by running calendar yourself - the calendar can be mailed to you, sent to the printer, and so on, first thing each morning. See below for an example calendar file and more information.
calendar builds a complicated egrep ( 27.5 ) expression to search your calendar file. You can see that expression yourself if you want to.
Let's start by showing a few lines of a sample calendar file. (Yours can be much longer.) Then I'll run calendar to show what lines it picks:
%cat calendar-- WORK -- 12/28 Project report due tomorrow! -- PERSONAL -- * 8 rub Lisa's feet Take Lisa out to dinner on December 8 dec 9 buy Lisa lunch On 12/10, Lisa will be hungry for ice cream -- BIRTHDAYS -- 1/1 Mom's birthday - make dinner reservations by 12/20! %dateTue Dec 8 08:43:40 PST 1992 %calendar* 8 rub Lisa's feet Take Lisa out to dinner on December 8 dec 9 buy Lisa lunch
Today is December 8. The
calendar
utility found lines in my
calendar
file for today and tomorrow.
calendar
understands lots of date formats. The date can be anywhere on a line. If you leave a line in your file for more than one year (like Mom's birthday)
calendar
will show it every year. If a line has more than one date, you'll see the line on both of those dates (I'll be reminded before Mom's birthday and also in time to make a dinner reservation). An asterisk (
*
) in place of a month means "all months."
Many versions of
calendar
utility run your
calendar
file through the C language preprocessor,
cpp
. Among other things, this lets you include several calendar files in your own calendar file. Lines that start with a hash mark (
#
) in column 1 are read by the preprocessor. For instance, this line in your
calendar
file would include all the contents of the file
/usr/local/lib/office.calendar
just as if you'd typed them into your own file:
#include "/usr/local/lib/office.calendar"
Someone (the office secretary) can maintain the
office.calendar
file. People in the office who want reminders from it can put the
#include
line in their own
calendar
files.
By the way, if you start a line with
#
and it's not for the preprocessor, you'll get a mysterious error like
calendar:
1:
undefined
control
. That means line 1 of the file had something the preprocessor couldn't understand.
How can
calendar
find dates in all the formats it accepts - and only for today and tomorrow? It runs a system program, usually named
/usr/lib/calendar
, that generates an expression for
egrep -f
(
27.7
)
. The expression searches for the dates of today and tomorrow; if today is a Friday, the expression includes dates on Saturday, Sunday, and Monday. Here's the expression I got by running
/usr/lib/calendar
on Tuesday, December 8. TAB characters are shown as
T
; spaces are shown as
.
%/usr/lib/calendar(^|[T(,;])((([Dd]ec[^
T]*|\*)[
T]*|(012|12|\*)/)0*8)([^0123456789]|$) (^|[
T(,;])((([Dd]ec[^
T]*|\*)[
T]*|(012|12|\*)/)0*9)([^0123456789]|$)
I'll turn the first line of that into English. I'm not writing this just for
egrep
fanatics
:-)
; this is also useful for understanding what kinds of dates
calendar
will recognize. I'm going to skip some not-so-subtle things like the nesting of the parentheses and just give an overview. If you haven't seen extended regular expressions before, see article
26.4
. The expression finds lines in your
calendar
file that meet these conditions, in order from left to right across the line:
(^|[
T(,;])
This matches whatever comes before the date. Match at the beginning of a line (
^
) or (
|
) match a space, TAB, opening parenthesis, comma, or semicolon (
[
). This keeps
egrep
from matching other words that start with or contain the month abbreviation
T(,;]
[Dd]ec
.
((([Dd]ec[^
T]*|\*)[
T]*|(012|12|\*)/)0*8)
This matches the date. Match
Dec
or
dec
with zero or more of any character besides space or TAB after that (
[Dd]ec[^
)-or (
T]*
|
) have a literal asterisk (
\*
), which means "match this on any month of the year." Or (
|
) match a numeric month like
012
or
12
or a literal asterisk (
(012|12|\*)
)-followed by a slash (
/
). Finally, you need today's date: it starts with any number of zeros and ends with
8
(
)0*8)
).
([^0123456789]|$)
The end of the expression matches lines anything except a digit - or matches the end of the line. This keeps egrep from matching non-dates like 8.75 .
Whew. That expression is repeated for every other day that needs to be matched. On Fridays, the output of /usr/lib/calendar has four lines - one each for Friday, Saturday, Sunday, and Monday.
If you want a calendar every weekday, put a line like the following into your personal crontab file ( 40.12 ) . We've split this onto two lines for printing, but you should type it all on one line:
$USER && < |
6 6 * * 1-5 tf=/tmp/cal.$USER; umask 077; /bin/calendar > $tf; test -s $tf && mail -s 'Calendar for today' $USER < $tf; rm -f $tf |
|---|
That runs
calendar
from my home directory at
6:06 a.m. (
40.5
)
every weekday morning. It sets a
Bourne shell variable (
6.8
)
named
tf
with the name of a temporary file in the
/tmp
directory (
21.3
)
, and sets a
umask
(
22.4
)
to make the file private. Then it runs
calendar
and saves the output in the temporary file. If there's a calendar for today, the
mail
command sends the file to me. (The
-s
option on our
mail
command adds the
Subject:
line
Calendar for today
to the message. It isn't required.) Finally, the temporary file is removed.
If you don't have personal crontab s, you can use a self-restarting at job ( 40.8 ) and the nextweekday script ( 40.10 ) instead.
-