thelinuxvault blog

Shell Script to Enhance the Calendar: Accepting MM, MMM, YYYY

The cal command in Unix-like systems is a handy tool for displaying calendars. However, by default, it might not accept dates in the formats of MM (two-digit month number), MMM (three-letter month abbreviation), and YYYY (four-digit year) in a very flexible way. In this blog post, we'll create a shell script that enhances the cal command to handle these input formats gracefully.

2026-05

Table of Contents#

  1. Understanding the cal Command Basics
  2. Parsing Input Formats (MM, MMM, YYYY)
  3. Writing the Shell Script
  4. Example Usage
  5. Best Practices and Common Pitfalls
  6. References

1. Understanding the cal Command Basics#

The cal command without any arguments displays the current month's calendar. If you provide a single argument (a number), it assumes it's a year and shows the calendar for that entire year. If you provide two arguments (month and year), it shows the calendar for that specific month and year. For example:

cal 12 2023  # Displays December 2023 calendar
cal 2023     # Displays the entire 2023 calendar

2. Parsing Input Formats (MM, MMM, YYYY)#

To handle MM, MMM, and YYYY formats, we need to convert the month abbreviation (MMM) to its corresponding number (MM). We can use an associative array (in Bash 4+). Here's how we can map month abbreviations to numbers:

declare -A month_map=( ["Jan"]="01" ["Feb"]="02" ["Mar"]="03" ["Apr"]="04" ["May"]="05" ["Jun"]="06" ["Jul"]="07" ["Aug"]="08" ["Sep"]="09" ["Oct"]="10" ["Nov"]="11" ["Dec"]="12" )

For MM format, we just need to ensure it's a valid two-digit number (between 01 and 12). And for YYYY, we can check if it's a four-digit number.

3. Writing the Shell Script#

Here's the full shell script (enhanced_cal.sh):

#!/bin/bash
 
# Check if the number of arguments is correct
if [ $# -ne 2 ]; then
    echo "Usage: $0 <MM/MMM> <YYYY>"
    exit 1
fi
 
month=$1
year=$2
 
declare -A month_map=( ["Jan"]="01" ["Feb"]="02" ["Mar"]="03" ["Apr"]="04" ["May"]="05" ["Jun"]="06" ["Jul"]="07" ["Aug"]="08" ["Sep"]="09" ["Oct"]="10" ["Nov"]="11" ["Dec"]="12" )
 
# Check if the year is a four-digit number
if ! [[ $year =~ ^[0-9]{4}$ ]]; then
    echo "Invalid year format. Please provide a four-digit year."
    exit 1
fi
 
# Handle month abbreviation (MMM)
if [[ ${#month} -eq 3 ]]; then
    if [[ -z ${month_map[$month]} ]]; then
        echo "Invalid month abbreviation. Please use a valid three-letter month abbreviation (e.g., Jan, Feb)."
        exit 1
    fi
    month=${month_map[$month]}
fi
 
# Check if the month (after conversion if needed) is a valid two-digit number
if ! [[ $month =~ ^[0-9]{2}$ ]] || (( month < 1 || month > 12 )); then
    echo "Invalid month. Please provide a valid two-digit month (01-12) or a valid three-letter abbreviation."
    exit 1
fi
 
cal $month $year

Make the script executable:

chmod +x enhanced_cal.sh

4. Example Usage#

  • Using MMM (month abbreviation):
./enhanced_cal.sh Jan 2024

This will display the January 2024 calendar.

  • Using MM (two-digit month number):
./enhanced_cal.sh 12 2023

This will display the December 2023 calendar.

5. Best Practices and Common Pitfalls#

  • Error Handling: Always check the input formats thoroughly as we did in the script. Invalid input can lead to unexpected behavior from the cal command.
  • Portability: The script uses Bash-specific features (like associative arrays). If you need more portability, you might consider using other shell scripting languages or implementing the month mapping in a more POSIX-compliant way (e.g., using case statements).
  • Testing: Test with a wide range of inputs (valid and invalid) to ensure the script works as expected. For example, test with an invalid month abbreviation (Jnn), an invalid year (202a), etc.

6. References#

This shell script provides a useful enhancement to the cal command, making it more user-friendly when dealing with different month and year input formats. You can further customize it based on your specific requirements, such as adding more error messages or integrating it with other scripts.