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!
How to do this with cron?
cp * ~/destination.0
cp * ~/destination.1
cp * ~/destination.0
cp * ~/destination.1
...and so on.
Any help would be greatly appreciated!
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))
+%s
) of today at 0:00 (-d 0:00
).(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.
Dec 1, 2017 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
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
.
+%w
: fuck the week has an odd number of days... then +%d
, then +%j
... then ... shit I'm fucked ...
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
destination.1
and have destination.0
as backup .. but actualy not alternating between two destinations.