2

Has anybody noticed that crontab doesnt seem to recognize ~ to mean the home directory?

I tried using a full expansion of /Users/username/filename.txt in crontab, which worked, but using ~/filename.txt results in failure.

Does anybody know why?

0

3 Answers 3

9

The question proposed using ~/username/filename.txt instead of /Users/username/filename.txt, but the proposed syntax should instead be either ~username/filename.txt or ~/filename.txt. For an illustration of a crontab entry which uses ~, see the top rated answer to Get low battery notifications for mouse earlier.

You can also test a simple example with this crontab entry:

* * * * * touch ~/NOT_A_FILE_I_CARE_ABOUT.txt
9
  • 3
    That is the first time I have seen ~ being said to work in a crontab, comments are usually made by manuals and writers that $HOME has to be used. (As macOS prefers launchd I have not written a cron job recently so I don't want to test this) A link to documentation would be useful here.
    – mmmmmm
    Jul 29 at 19:58
  • To be honest, I only know this because I have been using the low battery script for a while, and when I saw this question, I looked and saw that the crontab entry used ~. It might very well be safer to use $HOME, but ~ does seem to work. Jul 29 at 20:01
  • 1
    I suspect the issue here is that a proper Bourne shell sh does not understand a ~ But sh is not opensource so Apple uses bash as sh (by linking them) and bash running as sh is not 100% the same.
    – mmmmmm
    Jul 29 at 20:32
  • 2
    @mmmmmm /bin/sh understands ~. I tested on my Mac. I believe this is required by POSIX -- Bourne shell has been obsolete for decades and no OS uses it now.
    – Barmar
    Jul 30 at 15:37
  • 1
    ~ is recognized by POSIX, at least in recent editions: pubs.opengroup.org/onlinepubs/9699919799/utilities/…
    – Oskar Skog
    Jul 30 at 23:45
6

~ is a symbol shells automatically expand to $HOME, a standard /bin/sh (which cron uses to run the commands) does not need to support ~ expansion. The portable way is to use $HOME instead in your crontab file.

10
  • 5
    cron executes the command using /bin/sh. This understands ~ in MacOS.
    – Barmar
    Jul 29 at 17:05
  • @Barmar Ah, right.
    – nohillside
    Jul 30 at 6:51
  • there was an error in the original question, but the issue is still present. echo $HOME does correctly show the home directory. Any idea why else this could be happening? Jul 30 at 23:55
  • @Barmar: Not necessarily.
    – Seamus
    Jul 31 at 6:41
  • @CarriMegrabyan Use $HOME (or include the whole crontab file in your question, there may be other issues).
    – nohillside
    Jul 31 at 7:35
0

Some shells support ~, and some don't. Perhaps Apple uses dash as the default cron shell in Catalina, and bash in Monterey?; perhaps Apple changes the cron environment depending upon the phase of the moon?

Better than guessing what Apple has (or has not) done on some particular version of macOS, and on a machine that may or may not have user modifications... wouldn't it be better to run some simple tests - ask cron to tell you something about its environment? This would be an objective truth; one that requires no assumptions, and is not dependent upon vagaries in Apple's documentation.

Once a day (or whenever you wish), you can run a cron job that logs its environment and some other useful information from your system to a file. The file is always there, and its never more than 24 hours old (assuming your system was operating at the time you scheduled it).

A job similar to the one below in your crontab would answer your questions "definitively" (however see NOTE 3. below):

0 12 * * * (echo $(date); echo "What is '~'?:" ~; printenv) > /Users/seamus/mycronenv.txt 2>&1

This produces a file named mycronenv.txt in my $HOME directory that looks similar to this:

Sat Jul 30 23:35:00 CDT 2022
What is '~'?: /Users/seamus
SHELL=/bin/sh
MAILTO=
USER=seamus
PATH=/usr/bin:/bin
PWD=/Users/seamus
SHLVL=1
HOME=/Users/seamus
LOGNAME=seamus
_=/usr/bin/printenv

As you can see, my system's (Catalina) cron recognizes ~ as $HOME. To verify this, I added another job to my crontab (see NOTE 1. below):

* * * * * (echo "Write this line to the file ~/testdir/testfile with a timestamp: "; echo $(date)) >> ~/testdir/testfile.txt 2>&1

Which worked as expected, writing the result to $HOME/testdir/testfile.txt.

And since I used the append form of the redirect (>>), it adds a new entry every minute - i.e. remove this job after your test!

Hope this helps clear the confusion - please let us know if the issue persists, or you have other questions.


NOTES:
  1. If you want to try this on your machine, create the directory testdir first:

    % cd
    % mkdir testdir
    
  2. On my system (Catalina), Apple has set the default configuration to send mail to me with a note re my cron job - which is not something I want. Consequently, I have added a line to my crontab to disable that:

    MAILTO=""
    
  3. Wrt defitively:

    From man sh it seems that, rather than being definitive, Apple has given themselves some latitude: cron may use any one of three shells (bash, dash or zsh) in service of /bin/sh:

    sh is a POSIX-compliant command interpreter (shell). It is implemented by re-execing as either bash(1), dash(1), or zsh(1) as determined by the symbolic link located at /private/var/select/sh. If /private/var/select/sh does not exist or does not point to a valid shell, sh will use one of the supported shells.

11
  • 1
    Apple has been moving away from bash because of GPL issues, that's why zsh became the default Terminal shell in Catalina. It makes no sense that they would move to bash in Monterey. In any case, the shell used by cron has nothing to do with the Terminal shell. I believe POSIX requires that it be sh and implement its syntax.
    – Barmar
    Jul 31 at 19:32
  • @Barmar: You don't seem to understand what I'm saying. cron by default uses /bin/sh, but according to man sh (read Note3) /bin/sh may be bash, dash or zsh! The old 3.2 version of bash has been retained by Apple because all newer versions are covered under a different license! But according to Apple's own /man/sh they may execute bash when you (or cron) call for sh. "Makes no sense"... I'm just telling you what Apple's documentation says - feel free to pass your comment to Apple :) Your cmt, "I believe POSIX requires..." is not clear, but...
    – Seamus
    Aug 1 at 5:48
  • ... there is no POSIX requirement to use sh for any particular application.
    – Seamus
    Aug 1 at 5:49
  • man sh isn't the POSIX specification.
    – Barmar
    Aug 1 at 5:50
  • @Barmar: Of course not - who said it was? You can read man sh for yourself. It says that whatever shell is used for sh will be POSIX-compliant.
    – Seamus
    Aug 1 at 5:52

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .