execute_command and arguments that contain with blank spaces

Hi,

I tried two hours to pass an argument with a space to execute_process, but I didn’t find out how to do it. Cmake performs some magic quoting (“VERBATIM”). I tried using variables, various escaping, but I could not get it done.

My use case is quite simple: I would like to get a path without the last dir:

STRING(REGEX REPLACE /dir.*/ "x" PATH ${CMAKE_SOURCE_DIR}")

this does not work since it is always “greedy” and “/tmp/dir/src/dir” returns “tmpx” instead “/tmp/dir/srcx”. So I tried using some

execute_process(echo ${CMAKE_SOURCE_DIR} | bash -c 'stdin=$(cat); echo ${stdin%/dir/*}' OUTPUT_VARIABLE PATH)

in various variations, with escaping every character by \\, using variables with the argument and more, but I didn’t get it right.

Could someone show me how to correctly write

execute_process(bash -c 'echo a b c' OUTPUT_VARIABLE OUT)

to get “abc” in ${OUT} please?

Have you tried using get_filename_component?

Something like:

get_filename_component(parent_dir "${CMAKE_CURRENT_SOURCE_DIR}" DIRECTORY)

might give the desired result.

You would write it like this:

execute_process(COMMAND "bash" "-c" "echo a b c" OUTPUT_VARIABLE OUT)

but you would get a b c in OUT (i.e. including the spaces between a and b and c).

See the documentation of execute_process for more details.

I hope this helps!

1 Like

Hi!

Thanks so much for your helping and quick answer!

Yes, but I forgot to mention that in my case it normally is not the last component that I want to be removed, but all up to one with a specific name, let’s say “rootdir”:
/tmp/prj1/rootdir/src/legacystuff/prjold/rootdir/src/something --> /tmp/prj1/rootdir/src/legacystuff/prjold/
and the old bash script used path="${path%/rootdir/*}".

Ohh thank you!

Indeed! It is so simple! I was sure this was exactly what I tried first! I must have been made another mistake.

Yes, this helped a lot!

So now I wrote

execute_process(
  COMMAND "bash" "-c" "path=${CMAKE_SOURCE_DIR}; echo \${path%/vobs/*}"
  OUTPUT_VARIABLE ROOTDIR
  OUTPUT_STRIP_TRAILING_WHITESPACE)

and got exactly the expected result, thank you!

In meantime I noticed that string(FIND) has a REVERSE that also can be used:

        string(FIND "${CMAKE_SOURCE_DIR}" "/vobs/" INDEX REVERSE)
        string(SUBSTRING "${CMAKE_SOURCE_DIR}" 0 ${INDEX} ROOTDIR)

which might even be better because avoids dependency to bash, but in my case there are many different bash commands used anyway.

Thanks again!