Strip filename (shortest) extension by CMake (get filename removing the last extension)

I would do:

string(REGEX REPLACE "\\.[^.]*$" "" MYFILE_WITHOUT_EXT ${MYFILE})

The regular expression matches a dot (\\., see next paragraph), followed by any number of characters that is not a dot [^.]* until the end of the string ($), and then replaces it with an empty string "".

The metacharacter dot (normally in a regular expression it means "match any character") needs to be escaped with a \ to be interpreted as a literal dot. However, in CMake string literals (like C string literals), \ is a special character and need to be escaped as well (see also here). Therefore you obtain the weird sequence \\..

Note that (almost all) metacharacters do not need to be escaped within a Character Class: therefore we have [^.] and not [^\\.].

Finally, note that this expression is safe also if there's no dot in the filename analyzed (the output corresponds to the input string in that case).

Link to string command documentation.


I'd solve this with a simple regex:

string(REGEX MATCH "^(.*)\\.[^.]*$" dummy ${MYFILE})
set(MYFILE_WITHOUT_EXT ${CMAKE_MATCH_1})

As of CMake 3.14 it is possible to do this with get_filename_component directly.

NAME_WLE: File name without directory or last extension

set(INPUT_FILE a.b.c.d)
get_filename_component(OUTPUT_FILE_WE ${INPUT_FILE} NAME_WE)
get_filename_component(OUTPUT_FILE_WLE ${INPUT_FILE} NAME_WLE)

OUTPUT_FILE_WE would be set to a, and OUTPUT_FILE_WLE would be set to a.b.c.

Tags:

Cmake