Quantcast
Channel: User Kamil Maciorowski - Super User
Viewing all articles
Browse latest Browse all 645

Answer by Kamil Maciorowski for Cygwin find returns "missing argument to `-exec'"

$
0
0

As you have already found out, the fix is to use ; instead of \;. In my answer I will try to explain the mechanics behind this.

At first it's good to know why you need \; on Linux. It's not obvious, but find on Linux expects ; (or +) as an argument somewhere after -exec, not \;; see the specification from The Open Group, it says -exec utility_name [argument ...] ;. The backslash is for the shell. The problem is ; is special for the shell, it's a command terminator. If you used ;, the shell would interpret it as such, find wouldn't see it at all. To tell the shell ; should not be treated specially we can escape it with a backslash (\;) or we can quote it (";" or ';'). The shell will interpret and remove the backslash or the quotes and find will see sole ; it expects.

The path c:\cygwin64\bin\find.exe you used makes me believe you were not working in Bash (or similar shell) in Cygwin, but rather in cmd.exe. In cmd.exe; is not special, so there is no need to escape it. Additionally \ is not an escape character (^ is). \; you used got to find.exe literally as \;. The tool did not find ; (nor +) it expected, hence the error. Sole ; gets to find.exe as ; and this is what the tool expects.

AFAIK ";" in cmd.exe should ultimately get to find.exe as ;. ";" works on Linux as well, so we can call ";""universal syntax" in the context of this problem. Note ';' is not universal, single-quotes are not special in cmd.exe*.


* The situation is somewhat more complicated.

In Linux, executables like find get their arguments as an array (in your case: find, /backups/dummy-prod-db, -name, *_D_dummy-prod-db*, -type, f, -mtime, +7, -exec, rm, -v, {}, ;). The shell handles word splitting and globbing (in your case there were no unquoted wildcards though), it removes quotes, backslashes.

In Windows, executables like find.exe get their arguments as a single string. AFAIK technically before the Windows system calls main(), it calls _setargv() to parse the command line into the standard C argc and argv[] arguments that it passes to the main() function of the program. The program can provide its own _setargv(). This means that interpretation of quotes and wildcards like *, and splitting to words (separate arguments) are really the job of each executable alone, not of cmd.exe. The executable may use some standard _setargv(), then it's almost like cmd.exe did the job, a situation similar to what is in Linux; or it may provide its own _setargv().

Where I wrote

";" in cmd.exe should ultimately get to find.exe as ;

"ultimately" means "after _setargv()". Before _setargv() the quotes were there along with the rest of the command string; if find.exe provided a custom _setargv(), it could interpret these quotes in any way the author desired.

And where I wrote

single-quotes are not special in cmd.exe

I really meant "not special for commonly used _setargv()". If find.exe provided a custom _setargv(), it could interpret single-quotes in any way the author wanted, e.g. like single-quotes in Bash. I don't know, maybe your find.exe does interpret single-quotes like this.

In general a phrase "something works (or doesn't work) in cmd.exe" includes cmd.exeand some standard _setargv().

For comparison: FIND in Windows (the native FIND, not a port of *nix find) has its own peculiar syntax because it interprets the string it gets differently than any standard _setargv() would. You can find more information here: Tcler's Wiki / exec quotes problem (note some parts of the article are in the context of Tcl which has nothing to do with our problem, still the fragment about FIND is educative).


Viewing all articles
Browse latest Browse all 645

Trending Articles