0

This is driving me nuts as I know it is something easy, but I can't seem to find the solution. Arrgh! I just need to add a find command in to my script so it removes older files before running a new backup. I'd rather control this through variables instead of typing out the exact command. The command does work in the script if I type it out in there instead of using variables.

FIND="/usr/bin/find"
BUILD="~/"
FINDOPTS="-type f -mtime +3 -exec rm -rf {} \;"
echo $find $BUILD $FINDOPTS
## remove the 2 week old backup
echo "Removing old backups... "
$FIND $BUILD $FINDOPTS

If I just echo the $FIND $BUILD $FINDOPTS command it shows just like the command does if I type it out. Only difference is it will actually run when I type it.

Typing out /usr/bin/find ~/ -type f -mtime +3 -exec rm -rf {} \; works just fine.

The error that I get is:

/usr/bin/find: missing argument to `-exec'

Can anyone help explain why this is? Thank you!

3

Notwithstanding better overall solutions, here's the reason why it failed in this script:

FINDOPTS="-type f -mtime +3 -exec rm -rf {} \;"
                                            ^

The parameter find is waiting for is the character ;. Since ; is (not really by accident) also the shell's end of command delimiter, it has to be escaped in a shell command, hence usually typed \;. If now you put this character in a variable, it won't ever be evaluated by the shell as a delimiter. Thus it musn't be escaped.

Reproducing the error without variable:

$ find /etc -exec ls "\;"
find: missing argument to `-exec'

So just replace the string with:

FINDOPTS="-type f -mtime +3 -exec rm -rf {} ;"
  • Thank you. That solved my issue and you explained it nicely so that I understand exactly what is happening here. Really great answer, for me, at least. – saleetzo Mar 27 '18 at 21:26
2

Rather than find [...] -exec rm, I suggest using the built-in functionality:

find [...] -delete

From the manual:

 -delete
         Delete found files and/or directories.  Always returns true.  This executes 
         from the current working directory as find recurses down the tree.  It will 
         not attempt to delete a filename with a ``/'' character in its pathname 
         relative to ``.'' for security reasons.  Depth-first traversal processing 
         is implied by this option.  Following symlinks is incompatible with this 
         option.

(as an aside, you do realize that the command in your question will delete any files older than three days since their last modification, yes?)

  • Nice -- I never used -delete whenever using find commands for some reason. Always -exec or some xargs. I'll consider it for the future. Yeah, I just put a quick and dirty version in the example to find out where the issue was. The real command has some more specification in it and its not in the actual ~/ folder. Thanks tho! – saleetzo Mar 27 '18 at 20:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.