[bash] find: missing argument to -exec

I was helped out today with a command, but it doesn't seem to be working. This is the command:

find /home/me/download/ -type f -name "*.rm" -exec ffmpeg -i {} -sameq {}.mp3 && rm {}\;

The shell returns

find: missing argument to `-exec'

What I am basically trying to do is go through a directory recursively (if it has other directories) and run the ffmpeg command on the .rm file types and convert them to .mp3 file types. Once this is done, remove the .rm file that has just been converted.

I appreciate any help on this.

This question is related to bash shell find arguments exec

The answer is


If you are still getting "find: missing argument to -exec" try wrapping the execute argument in quotes.

find <file path> -type f -exec "chmod 664 {} \;"

Both {} and && will cause problems due to being expanded by the command line. I would suggest trying:

find /home/me/download/ -type f -name "*.rm" -exec ffmpeg -i \{} -sameq \{}.mp3 \; -exec rm \{} \;

A -exec command must be terminated with a ; (so you usually need to type \; or ';' to avoid interpretion by the shell) or a +. The difference is that with ;, the command is called once per file, with +, it is called just as few times as possible (usually once, but there is a maximum length for a command line, so it might be split up) with all filenames. See this example:

$ cat /tmp/echoargs
#!/bin/sh
echo $1 - $2 - $3
$ find /tmp/foo -exec /tmp/echoargs {} \;
/tmp/foo - -
/tmp/foo/one - -
/tmp/foo/two - -
$ find /tmp/foo -exec /tmp/echoargs {} +
/tmp/foo - /tmp/foo/one - /tmp/foo/two

Your command has two errors:

First, you use {};, but the ; must be a parameter of its own.

Second, the command ends at the &&. You specified “run find, and if that was successful, remove the file named {};.“. If you want to use shell stuff in the -exec command, you need to explicitly run it in a shell, such as -exec sh -c 'ffmpeg ... && rm'.

However you should not add the {} inside the bash command, it will produce problems when there are special characters. Instead, you can pass additional parameters to the shell after -c command_string (see man sh):

$ ls
$(echo damn.)
$ find * -exec sh -c 'echo "{}"' \;
damn.
$ find * -exec sh -c 'echo "$1"' - {} \;
$(echo damn.)

You see the $ thing is evaluated by the shell in the first example. Imagine there was a file called $(rm -rf /) :-)

(Side note: The - is not needed, but the first variable after the command is assigned to the variable $0, which is a special variable normally containing the name of the program being run and setting that to a parameter is a little unclean, though it won't cause any harm here probably, so we set that to just - and start with $1.)

So your command could be something like

find -exec bash -c 'ffmpeg -i "$1" -sameq "$1".mp3 && rm "$1".mp3' - {} \;

But there is a better way. find supports and and or, so you may do stuff like find -name foo -or -name bar. But that also works with -exec, which evaluates to true if the command exits successfully, and to false if not. See this example:

$ ls
false  true
$ find * -exec {} \; -and -print
true

It only runs the print if the command was successfully, which it did for true but not for false.

So you can use two exec statements chained with an -and, and it will only execute the latter if the former was run successfully.


For anyone else having issues when using GNU find binary in a Windows command prompt. The semicolon needs to be escaped with ^

find.exe . -name "*.rm" -exec ffmpeg -i {} -sameq {}.mp3 ^;

Try putting a space before each \;

Works:

find . -name "*.log" -exec echo {} \;

Doesn't Work:

find . -name "*.log" -exec echo {}\;

You need to do some escaping I think.

find /home/me/download/ -type f -name "*.rm" -exec ffmpeg -i {} \-sameq {}.mp3 \&\& rm {}\;

You have to put a space between {} and \;

So the command will be like:

find /home/me/download/ -type f -name "*.rm" -exec ffmpeg -i {} -sameq {}.mp3 && rm {} \;

Also, if anyone else has the "find: missing argument to -exec" this might help:

In some shells you don't need to do the escaping, i.e. you don't need the "\" in front of the ";".

find <file path> -name "myFile.*" -exec rm - f {} ;

Just in case anyone sees a similar "missing -exec args" in Amazon Opsworks Chef bash scripts, I needed to add another backslash to escape the \;

bash 'remove_wars' do
  user 'ubuntu'
  cwd '/'
  code <<-EOH
    find /home/ubuntu/wars -type f -name "*.war" -exec rm {} \\;
  EOH
  ignore_failure true
end

Just for your information:
I have just tried using "find -exec" command on a Cygwin system (UNIX emulated on Windows), and there it seems that the backslash before the semicolon must be removed:
find ./ -name "blabla" -exec wc -l {} ;


Examples related to bash

Comparing a variable with a string python not working when redirecting from bash script Zipping a file in bash fails How do I prevent Conda from activating the base environment by default? Get first line of a shell command's output Fixing a systemd service 203/EXEC failure (no such file or directory) /bin/sh: apt-get: not found VSCode Change Default Terminal Run bash command on jenkins pipeline How to check if the docker engine and a docker container are running? How to switch Python versions in Terminal?

Examples related to shell

Comparing a variable with a string python not working when redirecting from bash script Get first line of a shell command's output How to run shell script file using nodejs? Run bash command on jenkins pipeline Way to create multiline comments in Bash? How to do multiline shell script in Ansible How to check if a file exists in a shell script How to check if an environment variable exists and get its value? Curl to return http status code along with the response docker entrypoint running bash script gets "permission denied"

Examples related to find

Find a file by name in Visual Studio Code Explaining the 'find -mtime' command find files by extension, *.html under a folder in nodejs MongoDB Show all contents from all collections How can I find a file/directory that could be anywhere on linux command line? Get all files modified in last 30 days in a directory FileNotFoundError: [Errno 2] No such file or directory Linux find and grep command together find . -type f -exec chmod 644 {} ; Find all stored procedures that reference a specific column in some table

Examples related to arguments

docker build with --build-arg with multiple arguments ARG or ENV, which one to use in this case? How to have multiple conditions for one if statement in python Gradle task - pass arguments to Java application Angularjs - Pass argument to directive TypeError: method() takes 1 positional argument but 2 were given Best way to check function arguments? "Actual or formal argument lists differs in length" Python: Passing variables between functions Print multiple arguments in Python

Examples related to exec

I do not understand how execlp() works in Linux Running a Python script from PHP How do I execute a Shell built-in command with a C function? What are the uses of the exec command in shell scripts? php exec() is not executing the command How to call execl() in C with the proper arguments? Run Bash Command from PHP PHP shell_exec() vs exec() Ruby, Difference between exec, system and %x() or Backticks How to execute an external program from within Node.js?