Fixing Cron Syntax Errors When Using Backticks (`) in Command Substitution


2 views

When trying to schedule a PostgreSQL query that emails results with a timestamp in the subject line, many developers hit this common cron syntax error:

00 08 * * * psql -Uuser database < query.sql | mail someone@null.com -s "query for date +%Y-%m-%dZ%I:%M"

The error occurs because cron handles command substitution differently than your shell:

/bin/sh: -c: line 0: unexpected EOF while looking for matching '
/bin/sh: -c: line 1: syntax error: unexpected end of file

Cron uses its own special character escaping rules. The percent sign (%) has special meaning in crontab files, and backticks often get mangled during cron's parsing process. The cron daemon doesn't process the command through your normal shell environment first.

Here are three working approaches:

Option 1: Use $() syntax instead of backticks (preferred method)

00 08 * * * psql -Uuser database < query.sql | mail someone@null.com -s "query for $(date +\%Y-\%m-\%dZ\%I:\%M)"

Option 2: Escape percentage signs when using backticks

00 08 * * * psql -Uuser database < query.sql | mail someone@null.com -s "query for date +\%Y-\%m-\%dZ\%I:\%M"

Option 3: Wrap the command in a shell script

#!/bin/bash
psql -Uuser database < query.sql | mail someone@null.com -s "query for $(date +%Y-%m-%dZ%I:%M)"

Then call the script from cron:

00 08 * * * /path/to/your_script.sh
  • Always escape percentage signs (% → \%) in cron commands
  • Prefer $() over backticks for command substitution
  • For complex commands, move the logic into a separate shell script
  • Test your commands directly in the same shell that cron uses (usually /bin/sh)
  • Capture cron output by redirecting stderr to a log file for debugging

Remember that cron jobs run with a minimal environment. Always specify full paths to binaries and consider setting up the complete environment in your script.


When trying to automate a PostgreSQL query with email notification using cron, many developers encounter the backtick () syntax issue. The original command:

00 08 * * * psql -Uuser database < query.sql | mail somone@null.com -s "query for date +%Y-%m-%dZ%I:%M"

fails with the error:

/bin/sh: -c: line 0: unexpected EOF while looking for matching '
/bin/sh: -c: line 1: syntax error: unexpected end of file

Cron uses /bin/sh by default, which handles command substitution differently than bash. While bash supports both $(...) and backticks, cron's default shell often has issues with nested quotes and backticks.

Here are three working alternatives:

1. Using $() Syntax

00 08 * * * psql -Uuser database < query.sql | mail somone@null.com -s "query for $(date +\%Y-\%m-\%dZ\%I:\%M)"

2. Wrapping in a Shell Script

Create send_query.sh:

#!/bin/bash
psql -Uuser database < query.sql | mail somone@null.com -s "query for $(date +%Y-%m-%dZ%I:%M)"

Then in cron:

00 08 * * * /path/to/send_query.sh

3. Escaping Percent Signs

00 08 * * * psql -Uuser database < query.sql | mail somone@null.com -s "query for date +\%Y-\%m-\%dZ\%I:\%M"
  • Always use absolute paths in cron jobs
  • Consider environment variable differences
  • For complex commands, use shell scripts
  • Test commands directly in /bin/sh first

To troubleshoot cron issues:

# Check cron logs
grep CRON /var/log/syslog

# Test command directly with sh
/bin/sh -c 'your_command_here'