C++ system() not working when there are spaces in two different parameters

Adam Smith picture Adam Smith · Apr 1, 2012 · Viewed 19.9k times · Source

I'm trying to run a .exe that requires some parameters by using system().

If there's a space in the .exe's path AND in the path of a file passed in parameters, I get the following error:

The filename, directory name, or volume label syntax is incorrect.

Here is the code that generates that error:

#include <stdlib.h>
#include <conio.h>

int main (){
    system("\"C:\\Users\\Adam\\Desktop\\pdftotext\" -layout \"C:\\Users\\Adam\\Desktop\\week 4.pdf\"");
    _getch();
}

If the "pdftotext"'s path doesn't use quotation marks (I need them because sometimes the directory will have spaces), everything works fine. Also, if I put what's in "system()" in a string and output it and I copy it in an actual command window, it works.

I thought that maybe I could chain some commands using something like this:

cd C:\Users\Adam\Desktop;
pdftotext -layout "week 4.pdf"

So I would already be in the correct directory, but I don't know how to use multiple commands in the same system() function.

Can anyone tell me why my command doesn't work or if the second way I thought about would work?

Edit: Looks like I needed an extra set of quotation marks because system() passes its arguments to cmd /k, so it needs to be in quotations. I found it here:

C++: How to make a my program open a .exe with optional args

so I'll vote to close as duplicate since the questions are pretty close even though we weren't getting the same error message, thanks!

Answer

hamstergene picture hamstergene · Apr 1, 2012

system() runs command as cmd /C command. And here's citation from cmd doc:

If /C or /K is specified, then the remainder of the command line after
the switch is processed as a command line, where the following logic is
used to process quote (") characters:

    1.  If all of the following conditions are met, then quote characters
        on the command line are preserved:

        - no /S switch
        - exactly two quote characters
        - no special characters between the two quote characters,
          where special is one of: &<>()@^|
        - there are one or more whitespace characters between the
          two quote characters
        - the string between the two quote characters is the name
          of an executable file.

    2.  Otherwise, old behavior is to see if the first character is
        a quote character and if so, strip the leading character and
        remove the last quote character on the command line, preserving
        any text after the last quote character.

It seems that you are hitting case 2, and cmd thinks that the whole string C:\Users\Adam\Desktop\pdftotext" -layout "C:\Users\Adam\Desktop\week 4.pdf (i.e. without the first and the last quote) is the name of executable.

So the solution would be to wrap the whole command in extra quotes:

//system("\"D:\\test\" nospaces \"text with spaces\"");//gives same error as you're getting
system("\"\"D:\\test\" nospaces \"text with spaces\"\""); //ok, works

And this is very weird. I think it's also a good idea to add /S just to make sure it will always parse the string by the case 2:

system("cmd /S /C \"\"D:\\test\" nospaces \"text with spaces\"\""); //also works