Reputation: 7415
Consider the following CMD session on Windows 10, lines starting with #
are comments:
# We have this simple program
D:\testdir>type prg.c
#include <stdio.h>
int main() {
printf("Hello prg");
return 0;
}
# This is "realgcc.exe (Rev2, Built by MSYS2 project) 6.2.0"
D:\testdir>gcc prg.c -o prg
D:\testdir>prg.exe
Hello prg
D:\testdir>md dir
D:\testdir>cd dir
D:\testdir\dir>..\prg.exe
Hello prg
# This does not work however
D:\testdir\dir>../prg.exe
'..' is not recognized as an internal or external command,
operable program or batch file.
# But this does
D:\testdir\dir>"../prg.exe"
Hello prg
# Now we want to call the same program, from the same directory,
# but from C instead, so we create this file
D:\testdir\dir>type call.c
#include <stdlib.h>
int main() {
system("..\\prg.exe");
return 0;
}
D:\testdir\dir>gcc call.c -o call
D:\testdir\dir>call.exe
Hello prg
# Now to the question: If we modify the system function call
# to the following -- why doesn't it work?
D:\testdir\dir>type call.c
#include <stdlib.h>
int main() {
system("\"../prg.exe\"");
return 0;
}
D:\testdir\dir>gcc call.c -o call
D:\testdir\dir>call.exe
'..' is not recognized as an internal or external command,
operable program or batch file.
So apparently calling system
is not the same as running the command in a CMD session interactively? Are the quotes stripped for some reason? Is there another syntax that can be used to invoke executables in other directories using relative paths containing using /
instead of \
as separators?
(I noticed this when trying to make a Cygwin program and a usual Windows program talk to each other.)
Edit: Apparently, this works:
#include <stdlib.h>
int main() {
system("\"\"../prg.exe\"\"");
return 0;
}
Possibly related, in CMD,
cmd /c ""../prg.exe""
works, whereas this don't
cmd /c "../prg.exe"
So it seems that some additional quotes are needed for some reason in the system
call?
Upvotes: 2
Views: 358
Reputation: 7415
Thank you for all helpful comments, I now understand what's happening. I did not consider how the command (i.e., the argument to system
) is actually passed to the "command interpreter" when asking this question, and this is critical to consider to understand why the the outer quotes disappear.
On Windows, calling system("command")
is essentially the the same thing as spawning a new cmd.exe
process with the arguments /c
and command
. (On Linux and similar OSes, we would instead have an equivalence with sh -c command
.)
The problem here, however, is that in most cases Windows' CMD will strip the first and last quote character when a command is passed through the /c
flag. This is stated in the documentation given by cmd /?
:
[...]
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.
[...]
Upvotes: 1