Appending Dates To Filenames in Cron Jobs
As a heavy proponent of automation, I constantly use cron
to schedule tasks. A cron
is a utility available in Linux that allows you to schedule a command or script to run automatically at a specified time and date. A cron job is the name for the scheduled task.
Some of the tasks I set up cron jobs for are deleting temporary files, running commands, synchronise data folders and tasks that email me updates based on various gathered pieces of data.
I plan to do a full article on the cron
service in the future, but for now, I wanted to cover a recent gotcha I got asked for input into solving.
How do I append dates to filenames in cron jobs.
So it is quite common to want to append dates in filenames. We have probably all seen a script such as
#!/bin/bash
tar -cf backup-$(date +%Y-%m-%d-%H%M%S).tar file1.txt file2.txt
Those who don’t know what the tar
command does.
A quick tip - while I don’t want to get away from the point of this article, but if you didn’t require the hour, minutes and seconds, then we can modify the previous command; using backticks instead of
$()
and using thedate -I
syntax, less typing. See the example below.
The image below shows a file listing using the ls -l
command. The image shows two files called file1.txt and file2.txt, respectively. Using the tar
and date
commands, we make a tar
archive of the two files appended with the date and time at the end of the archive name.
We then show the listing again, and we can see the creation of backup-2021-03-27-152146.tar
. Next, we see a variation of command being run using just the date -I
enclosed in backticks. The output of this does not show the hours, minutes and seconds; however, it is faster to type and has another benefit we will see in a minute.
We have seen a typical use case of a command that appends the date. Why can’t I use this in a cron? Surely we can paste the above example in a script called mybackupscript.sh and run it every minute like the following… right!
# Example of job definition:
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# | | | | |
# * * * * * user-name command to be executed
*/1 * * * * root /root/mybackupscript.sh
Wrong - We can read the manual for the crontab man 5 crontab
to get our answer.
The “sixth” field (the rest of the line) specifies the command to be run. The entire command portion of the line, up to a newline or a “%” character, will be executed by /bin/sh or by the shell specified in the SHELL variable of the cronfile. A “%” character in the command, unless escaped with a backslash (), will be changed into newline characters, and all data after the first % will be sent to the command as standard input.
So how do we work around this?
Just as the excerpt says, we escape like so
#!/bin/bash
tar -cf backup-$(date +\%Y-\%m-\%d-\%H\%M\%S).tar file1.txt file2.txt
So, Saint? Why did you waste time showing us date -I
.... because it doesn’t contain a percentage sign ;-).