ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
If the first match is a directory, /bin/rm will not be able to remove it (because it is a directory), and therefore returns a nonzero exit status. A nonzero exit status will cause find to abort the search. That should not abort the search, though.
Anyway, To fix the issue, limit the search to files, and use the -f (force delete) flag for rm (to never prompt, and ignore if the file happens to vanish in the mean time -- it might have been a temporary file or something):
If the first match is a directory, /bin/rm will not be able to remove it (because it is a directory), and therefore returns a nonzero exit status. A nonzero exit status will cause find to abort the search.
What version of find do you have that behaves that way? Sounds seriously broken. What is supposed to happen is that find treats the result as true or false depending on the exit status and continues to evaluate the expression accordingly.
What version of find do you have that behaves that way?
Nominal Animal brainfart #1957264, apparently.
Quote:
Originally Posted by rknichols
What is supposed to happen is that find treats the result as true or false depending on the exit status and continues to evaluate the expression accordingly.
And that is exactly what happens using find (GNU findutils) 4.4.2) at least.
Is it possible OP's cron might de-escape the final \; for some reason -- a cron bug perhaps?
And that is exactly what happens using find (GNU findutils) 4.4.2) at least.
Is it possible OP's cron might de-escape the final \; for some reason -- a cron bug perhaps?
Not a bug - documented behaviour.
man 5 crontab
Code:
The ``sixth'' field (the rest of the line) specifies the command to be run. The entire command portion of the line, up to a newline
or % character, will be executed by /bin/sh or by the shell specified in the SHELL variable of the crontab file. Percent-signs (%)
in the command, unless escaped with backslash (\), will be changed into newline characters, and all data after the first % will be
sent to the command as standard input. There is no way to split a single command line onto multiple lines, like the shell's trailing
"\".
But I, too, have been bitten by this in the past ... anything but the simplest
bash things for me goes into shell-wrappers if I need to run it via cron ;D
The docu for cron on AIX is slightly more precise in the description of the
importance (and "features") of the backslash:
Code:
Note: Any character preceded by a backslash (including the %) causes that character to be treated literally.
Ah, that explains it, then: the shell consumes the semicolon which cron helpfully de-escaped, causing find to fail with find: missing argument to `-exec' . Good catch, Tink.
hypernetics, you can fix your command using ';' instead of \; although I do recommend you use the equivalent but faster and simpler find /backups -type f -mtime +2 -delete instead.
Not a bug - documented behaviour.
[SNIP]
The docu for cron on AIX is slightly more precise in the description of the
importance (and "features") of the backslash:
Code:
Note: Any character preceded by a backslash (including the %) causes that character to be treated literally.
Interesting. The cron daemon (cronie-1.4.4-7.el6) in RHEL-6 does not do that. The "\;" at the end of the command is passed literally to the find command, which works just as the OP intended.
Interesting. The cron daemon (cronie-1.4.4-7.el6) in RHEL-6 does not do that. The "\;" at the end of the command is passed literally to the find command, which works just as the OP intended.
Literally \;? Do you mean that cron passes it as-is to the shell, which de-escapes it to ; ? I'd expect the latter.
Or does cronie cron execute the command directly, without a shell? That is possible, but it would be a big departure from traditional crons.
In any case the differences indicate it is probably a bad idea to make any assumptions about how cron handles the command parameters wrt. escaping, and use a separate script instead, like Tinkster mentioned.
Literally \;? Do you mean that cron passes it as-is to the shell, which de-escapes it to ; ? I'd expect the latter.
Or does cronie cron execute the command directly, without a shell? That is possible, but it would be a big departure from traditional crons.
OK, my turn for a brain fart. The cron daemon passes it literally to the shell, which then passes just the ";" character as an argument to find.
I ran a few tests (while linuxquestions.org was down) and found that if the command is "simple" (no shell meta-characters, though simple quoted strings seem to bo OK), the cron daemon will indeed bypass the shell and directly exec() the command. For anything more complicated, the command line is passed with "-c" to a shell.
I ran a few tests (while linuxquestions.org was down) and found that if the command is "simple" (no shell meta-characters, though simple quoted strings seem to bo OK), the cron daemon will indeed bypass the shell and directly exec() the command. For anything more complicated, the command line is passed with "-c" to a shell.
Thanks; that is very interesting, and useful to know for me.
You see, for administration I often create a directory (typically /usr/local/bin/admin/) to put scripts that any user can run privileged using sudo. Instead of adding that directory to PATH and adding the one-line privilege escalation test at the start of the script, I prefer to create aliases similar to admin-task="sudo -- /usr/local/bin/admin/task" . While these tasks are only intended to be run interactively by humans, I now know the reason why it may fail if somebody puts one in cron: as it is an alias, it cannot be exec()d directly, which the cron may do if the command is simple. It is very useful to have it documented (in the README at that directory); thank you.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.