【发布时间】:2016-01-20 16:21:09
【问题描述】:
我想在execute_process 中调用命令find。
find命令的格式为:
find [/v] [/c] [/n] [/i] [/off[line]] "<String>" [[<Drive>:][<Path>]<FileName>[...]]
所以,字符串必须用双引号引起来。但是,如果我在 cmake 中这样做:
execute_process(COMMAND <firstCommandPipingSomethingToFind>
COMMAND find "<myString>" /c
OUTPUT_VARIABLE MY_COUNT
OUTPUT_STRIP_TRAILING_WHITESPACE)
我收到一个错误FIND: Parameter format not correct。
如果我使用 \ 转义双引号,则会收到错误 Access denied - \。
同样使用双转义 \\ 或双双引号 "" 也无济于事。
所以我的问题是:
有没有办法在调用execute_process 时转义双引号,以便find 正确接收它的参数?
我可以使用findstr,它不需要双引号;但是它不提供计数功能。我可以通过调用find /v /c "" 来使用find,但同样,我需要双引号!
而我想统计cmake外的输出行数,并将结果直接存储在MY_COUNT变量中。
注意:我使用的是CMake 3.4.1
要重现该问题,您可以使用以下代码,其中cmake -E echo 用于将字符串提供给findstr 和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}")
哪些输出:
0) DUMMY=hello
MyCommand=find "ell" /c
1) DUMMY=
2) DUMMY=
3) DUMMY=
4) DUMMY=
我也试过
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}")
哪些输出:
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)
如果删除/c 选项,问题也仍然存在。
这:
execute_process(COMMAND ${CMAKE_COMMAND} -E echo hello COMMAND find \"ell\" OUTPUT_VARIABLE DUMMY)
message (STATUS "DUMMY=${DUMMY}")
输出这个:
Access denied - \
DUMMY=
按照 Tsyvarev 的建议检索哪个字符串被有效传递到命令行,这个:
execute_process(COMMAND cmd /c echo \"ell\")
execute_process(COMMAND cmd /c echo "ell")
execute_process(COMMAND cmd /c echo ""ell"")
输出这个:
\"ell\"
ell
"" ell\"\"
第三个命令的警告:
Argument not separated from preceding token by whitespace.
This warning is for project developers. Use -Wno-dev to suppress it.
【问题讨论】:
-
嗯,转义序列
\"在 Linux 上被成功解释为"。根据execute_process documentation、CMake executes the child process using operating system APIs directly. All arguments are passed VERBATIM to the child process. No intermediate shell is used,因此这种行为在不同的操作系统上应该不会有所不同。您想查找什么 exact 字符串,以及您尝试了哪些确切的转义? (至少,在\"转义的情况下,字符 `\` 应该被 CMake 使用)。 -
哦,
COMMAND find \"ell\" /c应该可以了。从 CMake 变量中获取字符串是另一回事:set(MyArgument "ell")、COMMAND find "\"${MyArgument}\"" /c(外引号是可选的;仅当您的字符串包含空格时才需要它们)。在变量本身中存储引号有点复杂.. 但你确定要这样做吗? -
真的很奇怪:字符“\”应该被 CMake 解释器使用并且不应该传递给命令,但是“访问被拒绝 - \”......看起来 CMake 试图逃避事情(它不应该这样做),并且这样做不正确。你使用什么 CMake 版本?
-
顺便说一句,使用
COMMAND cmd /c echo <string>可以看到传递给命令的确切参数。有趣的是,在最后一种情况下会打印什么。 -
可能需要查看 CMake 的来源。或提交错误报告。
标签: windows cmake find findstr