0

I am having a problem with a bash command returning the following error:

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

The actual command I am running is:

/usr/bin/find /backup-directory/ -maxdepth 1 -type f -mtime +14 -printf "%f\n" -exec /usr/local/bin/aws s3 mv /backup-directory/{} s3://my-s3-bin/{}\;

The goal was to have this command called from the crontab nightly to search a directory and move any file older than 14 days to Amazon S3 using the aws cli.

The find command works correctly up until just before the -exec, with the following output:

/usr/bin/find /backup-directory/ -maxdepth 1 -type f -mtime +14 -printf "%f\n"
20161030002947.Pg
20161029002644.Pg
20161027002705.Pg
20161028002402.Pg
20161031002440.Pg

And just the aws cli move command with explicit file name to move works as intended: The following command will move 20161030002947.Pg for instance, from the local backup directory to the s3 bin.

/usr/local/bin/aws s3 mv /backup-directory/20161030002947.Pg s3://my-s3-bin/20161030002947.Pg

I don't know why it is breaking when I put them together with the -exec and {} parameters.

The reason everything is called from the full path is to make sure there are no unforeseen issues when the command is called from crontab, and the OS on this particular server is Debian 8.

Cyrus
  • 84,225
  • 14
  • 89
  • 153
Sheldon
  • 13
  • 2

1 Answers1

5

I suggest to replace

{}\; 

by

{} \;
Cyrus
  • 84,225
  • 14
  • 89
  • 153
  • That at least let it execute, so thank you. But now I am getting unexpected results. It looks like it might not be respecting the -printf "%f\n". 20161030002947.Pg The user-provided path /backup-directory//backup-directory/20161030002947.Pg does not exist. 20161029002644.Pg The user-provided path /backup-directory//backup-directory/20161029002644.Pg does not exist. – Sheldon Nov 15 '16 at 21:24
  • I just tested this with replacing the aws command with echo and I must have a misunderstanding of what the `-printf "%f\n"` does, because the full path is still getting put into `{}` ...This is the output with echo: `find /backup-directory/ -maxdepth 1 -type f -mtime +14 -printf "%f\n" -exec echo /backup-directory/{} s3:/my-s3-bin/{} \; 20161030002947.Pg /backup-directory//backup-directory/20161030002947.Pg s3://my-s3-bin//backup-directory/20161030002947.Pg` – Sheldon Nov 15 '16 at 21:51
  • Printf writes to stdout. it does not affect -exec. – that other guy Nov 15 '16 at 21:56
  • Cron has some unthinkably ridiculous handling of `%`. The easiest workaround is to put the command in a bash script and fire the script with cron. – Michael - sqlbot Nov 15 '16 at 22:05
  • That is what I'm finding unfortunately, that other guy. And finding that I'm not supposed to use loops on find, and not supposed to reference {} more than once. (http://unix.stackexchange.com/questions/321697/why-is-looping-over-finds-output-bad-practice) .... I don't know how I can make this work. passing anything but the file name itself to the aws cli will break because the path is different on S3. And the file name has to be explicit on S3 so I have to reference it twice, in both source and destination parameters. Can anyone help me with the right way to accomplish this? – Sheldon Nov 15 '16 at 22:43
  • I suggest to replace `%` by `\%` in a cronjob. `%` marks a newline in a cronjob. – Cyrus Nov 16 '16 at 06:26
  • Thanks everyone. In scope of the original question. the % was breaking the cronjob, and the lack of a space before the \; was stopping it from running. The remaining issues are with the logic of the command and I'll need to ask a separate question to get those addressed. – Sheldon Nov 16 '16 at 15:27
  • 1
    I was able to get it to work by using `sh -c` and `basename` along with the suggestions above. So a simplified example version to move all `filename` that meets the find criteria from `sourcedir` to `destinationbin` using aws cli would be: `find /sourcedir/ -maxdepth 1 -type f -mtime +14 -exec sh -c 'aws s3 mv /sourcedir/$(basename $1) s3://destinationbin/$(basename $1)' find-sh {} \;` ...This gets rid of the need for `%` entirely as `-printf` would only work if you were piping it. I used info from http://stackoverflow.com/questions/15627446/find-and-basename-not-playing-nicely to help. – Sheldon Nov 16 '16 at 16:45