I will like to call the command find
from within a execute_process
.
The format of the find
command is:
find [/v] [/c] [/n] [/i] [/off[line]] "<String>" [[<Drive>:][<Path>]<FileName>[...]]
So, the string has to be double quoted. However, if in cmake I do:
execute_process(COMMAND <firstCommandPipingSomethingToFind>
COMMAND find "<myString>" /c
OUTPUT_VARIABLE MY_COUNT
OUTPUT_STRIP_TRAILING_WHITESPACE)
I get an error FIND: Parameter format not correct
.
If I escape the double quotes with \
, I get an error Access denied - \
.
Also using double escaping \\
or double double quotes ""
does not help.
So my question is:
Is there a way to escape the double quotes when calling execute_process
so that find
receives correctly its argument?
I could use findstr
, which doesn't need the double quotes; however it doesn't provide a counting feature. I could use find
by calling find /v /c ""
, but again, I need double quotes!
And I would like to count the output lines outside cmake, and store directly the result in MY_COUNT
variable.
Note: I am using CMake 3.4.1
To reproduce the problem you can use the following code, in which cmake -E echo
is used to feed a string to findstr
and find
:
#This works
execute_process(COMMAND ${CMAKE_COMMAND} -E echo hello COMMAND findstr ell OUTPUT_VARIABLE DUMMY)
message (STATUS "0) DUMMY=${DUMMY}")
#All of the following don't work
set(MyCommand "find \"ell\" /c")
execute_process(COMMAND ${CMAKE_COMMAND} -E echo hello COMMAND "${MyCommand}" OUTPUT_VARIABLE DUMMY)
message (STATUS MyCommand=${MyCommand})
message (STATUS "1) DUMMY=${DUMMY}")
execute_process(COMMAND ${CMAKE_COMMAND} -E echo hello COMMAND ${MyCommand} OUTPUT_VARIABLE DUMMY)
message (STATUS "2) DUMMY=${DUMMY}")
execute_process(COMMAND ${CMAKE_COMMAND} -E echo hello COMMAND MyCommand OUTPUT_VARIABLE DUMMY)
message (STATUS "3) DUMMY=${DUMMY}")
execute_process(COMMAND ${CMAKE_COMMAND} -E echo hello COMMAND "find \"ell\" /c" OUTPUT_VARIABLE DUMMY)
message (STATUS "4) DUMMY=${DUMMY}")
Which outputs:
0) DUMMY=hello
MyCommand=find "ell" /c
1) DUMMY=
2) DUMMY=
3) DUMMY=
4) DUMMY=
I also tried
set(MyArgument "\"ell\" /c")
message (STATUS MyArgument=${MyArgument})
execute_process(COMMAND ${CMAKE_COMMAND} -E echo hello COMMAND find "${MyArgument}" OUTPUT_VARIABLE DUMMY)
message (STATUS "1) DUMMY=${DUMMY}")
execute_process(COMMAND ${CMAKE_COMMAND} -E echo hello COMMAND find ${MyArgument} OUTPUT_VARIABLE DUMMY)
message (STATUS "2) DUMMY=${DUMMY}")
set(MyArgument "\"ell\"")
message (STATUS MyArgument=${MyArgument})
execute_process(COMMAND ${CMAKE_COMMAND} -E echo hello COMMAND find "${MyArgument}" /c OUTPUT_VARIABLE DUMMY)
message (STATUS "1) DUMMY=${DUMMY}")
execute_process(COMMAND ${CMAKE_COMMAND} -E echo hello COMMAND find ${MyArgument} /c OUTPUT_VARIABLE DUMMY)
message (STATUS "2) DUMMY=${DUMMY}")
Which outputs:
MyArgument="ell" /c
File not found - \ELL\
1) DUMMY=
File not found - \ELL\
2) DUMMY=
MyArgument="ell"
Access denied - \
1) DUMMY=
Access denied - \
2) DUMMY=
CMake Error at CMakeRules.cmake:404 (execute_process):
execute_process given COMMAND argument with no value.
Call Stack (most recent call first):
CMakeLists.txt:24 (include)
The problem persists also if a remove the /c
option.
This:
execute_process(COMMAND ${CMAKE_COMMAND} -E echo hello COMMAND find \"ell\" OUTPUT_VARIABLE DUMMY)
message (STATUS "DUMMY=${DUMMY}")
outputs this:
Access denied - \
DUMMY=
Following Tsyvarev suggestion to retrieve which string is effectively passed to the command line, this:
execute_process(COMMAND cmd /c echo \"ell\")
execute_process(COMMAND cmd /c echo "ell")
execute_process(COMMAND cmd /c echo ""ell"")
outputs this:
\"ell\"
ell
"" ell\"\"
With a warning for the third command:
Argument not separated from preceding token by whitespace.
This warning is for project developers. Use -Wno-dev to suppress it.