Cron Expression: Every 2 Weeks (Biweekly)
Cron counts days and months, not weeks, so there is no single line for “every 2 weeks.” The reliable pattern is to run weekly and skip on alternate weeks using the ISO week number. Here is the exact gate.
Why cron can't do biweekly alone
The day-of-month field resets every month and the day-of-week field has no “every other week” notion, so no combination of fields gives a stable 14-day cycle across month and year boundaries.
The common wrong answer
0 9 */14 * * looks biweekly but */14 on day-of-month fires on the 1st, 15th, and 29th, then resets — so runs land on the 29th and then the 1st, only three days apart. It is not a true 14-day cycle.
The correct pattern
Run every Monday at 9:00 and gate on the ISO week number being even (or odd):
0 9 * * 1 in cron, then: [ $(( $(date +%V | sed 's/^0//') % 2 )) -eq 0 ] || exit 0. %V is the ISO week (01–53); keeping even weeks gives a clean every-other-Monday schedule. Swap -eq 0 for -eq 1 to shift the phase.
Caveat at year end
A year with 53 ISO weeks means two odd weeks meet at the boundary, causing one 7-day gap instead of 14 once every few years. For most reporting jobs that is acceptable; if not, track the last run in a timestamp file and require 14 days elapsed.
FAQ
Is there a cron expression for every 2 weeks?
Not in one line — cron has no week counter. Run weekly (0 9 * * 1) and gate the script on the ISO week number modulo 2.
Why is 0 9 */14 * * wrong for biweekly?
*/14 on day-of-month fires on the 1st, 15th, and 29th, then resets each month, so the 29th and the next 1st are only days apart — not a true 14-day cycle.
How do I keep exact 14-day spacing?
Store the last run time in a file and require that 14 days have elapsed before the script proceeds; this survives 53-week years.