Shell scripting using the date command

Posted in Linux/Unix/BSD -

A useful command line tool is date, which is typically used for displaying the current system date, or setting it. The default format of the date and time displayed will be the system default, eg "Fri Dec 7 16:41:08 NZDT 2007", but it is possible to apply your own formatting, and also to specify a different date to use, without adjusting the system clock.

I manage a few dedicated web servers and they all run various automatic processes using cron, for doing MySQL database backups, processing Apache logfiles into meaningful statistics using AWStats, and so on. I frequently use the date command, embedded within other commands, in these automatic scripts.

If, for example, you wanted to display the current day's day of the week only, you would do this:

date +%A

The + switch tells the date command to apply the following format to the current date. %A tells date that the format to use is the locale's full weekday name. A full list of the formatting modifiers is at the end of this article. It's Friday today, so entering the above command at the command prompt would display this:

$ date +%A

If you wanted to display the date in the format YYYY-MM-DD, with a 4 digit year and 2 digit months with leading zeros, you would do this:

$ date +%Y-%m-%d

Specifying different dates

That was pretty easy, but the above examples only show the current system date. What if you wanted to show yesterday's date? There's another switch for date which allows you to specify a date other than the current one, the -d switch. The great thing with -d is you can use words to specify previous or future dates, as per the examples below.

In the examples below, the current date would return as "2007-12-07" and current day of the week would return as "Friday".

$ date +%Y-%m-%d -d yesterday

$ date +%A -d yesterday

$ date +%A -d "2 days ago"

$ date +%A -d "tomorrow"

$ date +%A -d "2 days"

$ date +%Y-%m-%d -d '3 weeks ago'

$ date +%Y-%m-%d -d '1 year ago'

Using date in other commands

Within the bash shell you can embed commands within other commands using backticks. As a very simple example, we'll use the echo command. The first example is without backticks so will just echo the word "date" the second example uses backticks and does echo the date. You wouldn't normally do this because date echoes the output anyway.

$ echo date

$ echo `date`
Fri Dec 7 16:57:15 NZDT 2007

As a slightly better example, I have a process on all my web servers that dumps all MySQL databases in backup text files in the early hours of the morning. I store one set of backups for each day of the week, so the backup directory has seven subdirectories like so:

$ ls -l /var/mysql-backup/
total 7
drwxr-xr-x 17 root root 1024 Nov 23 10:19 Friday
drwxr-xr-x 18 root root 1024 Nov 23 10:19 Monday
drwxr-xr-x 19 root root 1024 Nov 24 02:00 Saturday
drwxr-xr-x 18 root root 1024 Nov 23 10:19 Sunday
drwxr-xr-x 17 root root 1024 Nov 23 10:19 Thursday
drwxr-xr-x 18 root root 1024 Nov 23 10:19 Tuesday
drwxr-xr-x 18 root root 1024 Nov 23 10:19 Wednesday

To echo the contents of the current day of the week's backups, I would enter this at the command line:

ls -l /var/mysql-backup/`date +%A`

Date format specifiers

The following are the available date format specifiers:

%%     a literal %
%a     locale's abbreviated weekday name (e.g., Sun)
%A     locale's full weekday name (e.g., Sunday)
%b     locale's abbreviated month name (e.g., Jan)
%B     locale's full month name (e.g., January)
%c     locale's date and time (e.g., Thu Mar  3 23:05:25 2005)
%C     century; like %Y, except omit last two digits (e.g., 21)
%d     day of month (e.g, 01)
%D     date; same as %m/%d/%y
%e     day of month, space padded; same as %_d
%F     full date; same as %Y-%m-%d
%g     last two digits of year of ISO week number (see %G)
%G     year of ISO week number (see %V); normally useful only with %V
%h     same as %b
%H     hour (00..23)
%I     hour (01..12)
%j     day of year (001..366)
%k     hour ( 0..23)
%l     hour ( 1..12)
%m     month (01..12)
%M     minute (00..59)
%n     a newline
%N     nanoseconds (000000000..999999999)
%p     locale's equivalent of either AM or PM; blank if not known
%P     like %p, but lower case
%r     locale's 12-hour clock time (e.g., 11:11:04 PM)
%R     24-hour hour and minute; same as %H:%M
%s     seconds since 1970-01-01 00:00:00 UTC
%S     second (00..60)
%t     a tab
%T     time; same as %H:%M:%S
%u     day of week (1..7); 1 is Monday
%U     week number of year, with Sunday as first day of week (00..53)
%V     ISO week number, with Monday as first day of week (01..53)
%w     day of week (0..6); 0 is Sunday
%W     week number of year, with Monday as first day of week (00..53)
%x     locale's date representation (e.g., 12/31/99)
%X     locale's time representation (e.g., 23:13:48)
%y     last two digits of year (00..99)
%Y     year
%z     +hhmm numeric timezone (e.g., -0400)
%Z     alphabetic time zone abbreviation (e.g., EDT)