Home > database >  Cron stops the script if the file is not found
Cron stops the script if the file is not found

Time:08-09

I have the following simple script:

#!/bin/sh

a() {
  echo 1
}

a

b() {
  for file in "${DOWNLOADS}"123_*; do
    mv "${file}" "${DOWNLOADS}321"
  done
}

b

c() {
  echo 2
}

c

it is executable and if I call it from the terminal it works exactly right: a, b, c. But if I try to execute it via cron and there is no "123_{something}" file in the "${DOWNLOADS}" directory, then only function a is executed, and the beginning of the foor loop. Function c is not called because the script stops.

crontab -l

=>

10 20 * * * zsh /user/file

Debugging showed the following:

10 20 * * * zsh /user/file >> ~/tmp/cron.txt 2>&1

=>

 /user/file:47> a
 a:1> echo 1
1
 /user/file:67> b
file:12: no matches found: /Users/ivan/Downloads/123_*

As can be seen the execution of the script stopped immediately after the file was not found.

I don't understand why the execution of this script via cron stops if the file is not found, and how this can be avoided; can anyone explain this?

Or maybe it's just the limitations of my environment?

CodePudding user response:

I don't understand why the execution of this script via cron stops if the file is not found, and how this can be avoided; can anyone explain this?

Using globs that don't match anything is an error:

% print nope
zsh: no matches found: nope*

You can fix this by setting the null_glob option:

% setopt null_glob
% print nope*
[no output, as nothing was found]

You can set this for a single pattern by adding (N) to the end:

% print nope*(N)

So in your example, you end up with something like:

b() {
  for file in ${DOWNLOADS}123_*(N); do
    mv $file ${DOWNLOADS}321
  done
}

NOTE: this only applies to zsh; in your script you have #!/bin/sh at the top, but you're running it with zsh. It's best to change that to #!/usr/bin/env zsh if you plan on using zsh.

In standard /bin/sh, it behaves different: a pattern that doesn't match gets replaced by the pattern itself:

% sh
$ echo nope*
nope*

In that case, you need to check if $file in the loop matches nope* and continue if it does. But you're running zsh so it's not really applicable: just be aware that /bin/sh and zsh behave quite different with the default settings (you can also get the same behaviour in zsh if you want with setopt no_nomatch).

  • Related