Gerry
Gerry

Reputation: 207

Forfiles /P command issue (not documented?)

I have a scenario:

FORFILES /P "C:\users\DominiqueGerry\Work Files\" /S /M *.doc /C "cmd /c echo @fsize"

gives me an error:

ERROR: Invalid argument/option - '@fsize'.

Type "FORFILES /?" for usage.

But when I remove the slash, it works:

FORFILES /P "C:\users\DominiqueGerry\Work Files" /S /M *.doc /C "cmd /c echo @fsize"

I do not understand why this does not work without the backslash, but does not with it. I cannot find any official documentation explaining this. and do not even see any of it mentioned when running help forfiles /? I would appreciate any help on this.

The best part is. The error is not even related to the issue at hand.

Upvotes: 4

Views: 1733

Answers (2)

user7818749
user7818749

Reputation:

To be honest, I do not think it is documented anywhere in the official help (at least not what I have seen), but what actually happens is that the trailing backslash is actually escaping the last double quote. In my mind, this is actually a bug.

The reason why the error is not related is simply because the forfiles command detects an error in the format, due to the missing double quote, which the backslash escaped.

You will see that this does not happen when you do not have the double quotes, so let's assume you have no space in your path:

FORFILES /P C:\users\DominiqueGerry\WorkFiles\ /S /M *.doc /C "cmd /c echo @fsize"

Would not give you an error, simply because the baskslash does not have any valid character to escape, problem is, you do have a space in path, so you must use double quotes. So it is best to retain the double quotes and not add the trailing backslash:

FORFILES /P "C:\users\DominiqueGerry\Work Files" /S /M *.doc /C "cmd /c echo @fsize"

Or if you are adamant on using the backslash, simply escape it by doubling up.

FORFILES /P "C:\users\DominiqueGerry\Work Files\\" /S /M *.doc /C "cmd /c echo @fsize"

Edit, also as mentioned in comments by @aschipfl you can use .:

FORFILES /P "C:\users\DominiqueGerry\Work Files\." /S /M *.doc /C "cmd /c echo @fsize"

Upvotes: 6

michael_heath
michael_heath

Reputation: 5372

C/C++ sources compiled into executables may follow Parsing C++ Command-Line Arguments

Microsoft C/C++ startup code uses the following rules when interpreting arguments given on the operating system command line:

  • Arguments are delimited by white space, which is either a space or a tab.

  • The caret character (^) is not recognized as an escape character or delimiter. The character is handled completely by the command-line parser in the operating system before being passed to the argv array in the program.

  • A string surrounded by double quotation marks ("string") is interpreted as a single argument, regardless of white space contained within. A quoted string can be embedded in an argument.

  • A double quotation mark preceded by a backslash (\") is interpreted as a literal double quotation mark character (").

  • Backslashes are interpreted literally, unless they immediately precede a double quotation mark.

  • If an even number of backslashes is followed by a double quotation mark, one backslash is placed in the argv array for every pair of backslashes, and the double quotation mark is interpreted as a string delimiter.

  • If an odd number of backslashes is followed by a double quotation mark, one backslash is placed in the argv array for every pair of backslashes, and the double quotation mark is "escaped" by the remaining backslash, causing a literal double quotation mark (") to be placed in argv.

Quite common for C++ programs. The command interpreter started it's life before the C++ argument handling mentioned was established. reg.exe and other programs compiled from C++ sources usually have this argument handling.

forfiles.exe is not a builtin command to the command interpreter, so the builtin help of cmd.exe will not inform you of how external executables may behave.

As you have found, you can escape a double quote with a backslash i.e. \". This allows you to have double quotes in string within double quotes i.e. "\"string\"" so that the quotes are retained by the program that the argument has been passed to. To escape the escape, double up the backslash i.e. \\.

The error you receive is 1 double quote of a pair being removed and the escaped double quote is retained, thus the remaining double quote causes a syntax error.

Upvotes: 0

Related Questions