How to copy every day to another of two destinations?

One Liner:

0 0 * * * cp /path/to/* /path/to/destination.$(( $(date -d $(date +%F) +%s)/(3600*24) % 2))

Explanation:

$(( $(date -d 0:00 +%s)/(3600*24) % 2))
  • will return timestamp in seconds (+%s) of today at 0:00 (-d 0:00).
  • Divided by (3600*24) will return number of days from unix epoch.
  • %2 will return 0 or 1 for odd or even days since start of unix epoch.

I agree with the "run the cronjob daily, switch directories in the script" answers, but I'd do it like this:

#!/bin/bash 
# use hidden link
last=$HOME/.last_destination
#
declare -a dirs
dirs[0]="destination.0"
dirs[1]="destination.1"
#
target=
#
# If $last is a link, it points to the last used directory. Otherwise,
# initialize it and use $HOME/destination.0
if [[ -L "$last" ]] ; then
    # get the name of the linked dir
    old="$(stat  --printf="%N" "$last" | cut -d\' -f4)"
    if [[ "$old" == "${dirs[0]}" ]] ; then
        target="${dirs[1]}"
    else
        target="${dirs[0]}"
    fi
else
    # "$last" is not a link - first time initialization
    target="${dirs[0]}"
fi
# now, with $target set, point the $last link at $target, for next time
rm "$last"
ln -s "$target" "$last"
#
# debugging printouts - remove in real life
echo "$target"
ls -l "$last"

If it would be OK to write to ~/destination.0 on even dates and ~/destination.1 on odd dates, the following crontab line should work. It starts the backup at midnight (0 min, 0 hour, the two first items on the line),

0 0 * * * echo cd dir2copy;dtmp=$(( $(/bin/date '+%d') % 2 ));echo /bin/cp * ~/destination."$dtmp"

See this link for an explanation of the crontab syntax,

Scheduling Tasks with Cron Jobs

Test the command part of the line in a terminal window,

echo cd dir2copy;dtmp=$(( $(/bin/date '+%d') % 2 ));echo /bin/cp * ~/destination."$dtmp"

and when it works, you can replace cd dir2copy with cd to-the-actual-directory-you-want-to-copy, replace ~ with /home/your-home-directory and remove the two echo words to make it do the real job.

Test it again, and then modify the crontab line. (The environment in crontab is such that you may need explicit full paths to programs, directories and data files.)


/bin/date '+%d' finds the day of month and % is the remaindering operation, that produces a 0 or 1, which is appended at the end of the command line.

You may prefer /bin/date '+%j', which finds the day of year, for example today, Dec 1, is day #335.