4

I am hoping to run some of the commands listed in this article, e.g.:

cal -3

which is supposed to show me the last month, this month, and next month.

This command does not work in OS X.

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

Is there an alternative form I could use in OS X?

For reference:

$ which cal
/usr/bin/cal

and

$ man cal 

reveals that this is probably the default OS X version: "...BSD General Commands Manual..."

Amelio Vazquez-Reina
  • 40,169
  • 77
  • 197
  • 294
  • Where *is* the question? That aside, the linked articel is clearly titled "**Ubuntu Linux** Tip: [...]". While commands often have the same name on the different derivatives, the specific implementations may differ quite a lot, so in general there in no guarantee that any command line option is the same between Ubuntu and OS X. In this case it seems to be the "same" implementation of cal, but the one Ubuntu uses is from 2009 and significantly newer then the one on OS X from 2004. – Adaephon Feb 02 '15 at 14:21
  • The [OS X version](https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/ncal.1.html) seems a lot older. – muru Feb 02 '15 at 14:21

2 Answers2

5

OSX does not have the same version of utilities as Linux. The common denominator you can count on is POSIX, which defines cal but none of its options.

There are two common versions of cal on Linux: the one from util-linux (e.g. on Fedora) and the one from FreeBSD (e.g. on Ubuntu). Both have the -3 option. OSX is based on FreeBSD, but its version is an older one that doesn't have the -3 option.

You can emulate it with a bash/zsh script:

#!/bin/bash
case $# in
  0) month=$(date +%m) year=$(date +%Y);;
  2) month=$1 year=$2;;
  *) echo 1>&2 "Usage: $0 [MONTH YEAR]"; exit 3;;
esac
month=${month#"${month%%[!0]*}"}
if ((month == 1)); then
  previous_month=12 previous_year=$((year-1))
else
  previous_month=$((month-1)) previous_year=$year
fi
if ((month == 12)); then
  next_month=1 next_year=$((year+1))
else
  next_month=$((month+1)) next_year=$year
fi
paste <(cal "$previous_month" "$previous_year") \
      <(cal "$month" "$year") \
      <(cal "$next_month" "$next_year")
Gilles 'SO- stop being evil'
  • 807,993
  • 194
  • 1,674
  • 2,175
1

I'm so used to the Linux version of cal, that I went ahead and ported the Debian version of bsdmainutils which include the cal and ncal executables to a Homebrew formula, which you can find here.

Ironically, these utilities actually come from the FreeBSD upstream source code, but Apple hasn't bothered updated them in many years.

b4hand
  • 111
  • 2