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
).