How to do this with cron?

  • Today: cp * ~/destination.0
  • Tomorrow: cp * ~/destination.1
  • Next day: cp * ~/destination.0
  • Next day: cp * ~/destination.1

...and so on.

Any help would be greatly appreciated!

  • Yes, I will use rsync, cp was just for the example – Stefan Dec 2 '17 at 15:15

One Liner:

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


$(( $(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.
  • % 2 is simple a modulo operation, which returns 1 if the days number given to it is odd and 0 if it is even. – Videonauth Dec 1 '17 at 13:49
  • +1 for the solution using the seconds since 1970-01-01 00:00:00 UTC option. On this way you don't have to think about the 30/31 days/months problem of other attempts here – derHugo Dec 1 '17 at 14:20
  • @RoVo that's exactly what I've looked for because of the two odd days 31 and 1 ! Very smart! – Stefan Dec 2 '17 at 15:20
  • True. I updatet the answer. – pLumo Dec 2 '17 at 17:18

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

# use hidden link
declare -a dirs
# 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
    # "$last" is not a link - first time initialization
# 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.

  • will not alternate between day 365 and 1. – pLumo Dec 1 '17 at 14:17
  • 1
    Yes, you are right @RoVo . I noticed, that you have fixed that, and I will upvote your answer :-) You have spent more effort than I to make things work exactly according to the specification in the question. It would be OK for me at new year, that the alternation would skip. My computer might be turned off anyway ;-) – sudodus Dec 1 '17 at 14:24
  • True, but I started with the same problem ... +%w: fuck the week has an odd number of days... then +%d, then +%j... then ... shit I'm fucked ... – pLumo Dec 1 '17 at 14:26
  • Anyways after a leap year +%j will work correctly on new year ^^ – pLumo Dec 1 '17 at 14:29
  • not if the leap year is %100 :P – derHugo Dec 1 '17 at 14:31

Run this script daily from cron:

#! /bin/sh
set -e
cp * ~/destination.0
mv ~/destination.0 ~/destination.last
mv ~/destination.1 ~/destination.0
mv ~/destination.last ~/destination.0
  • you never write anything to ~/destination.1... – derHugo Dec 1 '17 at 13:55
  • Right, there's a bug in my (untested) script, the last line should rename *.last to *.1 instead of *.0... and in the meantime I've seen better solutions involving modulo 2 computations – Luc Moreau Dec 1 '17 at 14:23
  • Even than you would every day copy to destination.1 and have destination.0 as backup .. but actualy not alternating between two destinations. – derHugo Dec 1 '17 at 14:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.