How to find directories with a specific name pattern?

We have a windows file share folder/directory that warehouses 3rd party packages for us.

It has path value such as: //fs1/0.3rdparty

I want to find all the subfolders named Win-VS2022.

For example, I want the result to be

//fs1/0.3rdparty/foo/Win-VS2022
//fs1/0.3rdparty/bar/Win-VS2022
//fs1/0.3rdparty/pdq/Win-VS2022

I’ve tried logic such as:

cmake_path(CONVERT "$ENV{THIRD_PARTY_ROOT}" TO_CMAKE_PATH_LIST THIRD_PARTY_ROOT)
cmake_print_variables(THIRD_PARTY_ROOT)
file(GLOB_RECURSE VS2022_FOLDERS LIST_DIRECTORIES true
    "${THIRD_PARTY_ROOT}/*Win-VS2022")
cmake_print_variables(VS2022_FOLDERS)

I can confirm that the THIRD_PARTY_ROOT variable is correct.

However, the folders that are returned are not correct.

I will get incorrect results such as:

//fs1/deployment/0.3rdParty/foo/Win-VS2019/dependencies
//fs1/deployment/0.3rdParty/foo/Win-VS2022/dependencies

the first doesn’t even contain the Win-VS2022 while the second is beyond the matching string.

I’ve tried other glob variations too, such as

file(GLOB_RECURSE VS2022_FOLDERS LIST_DIRECTORIES true
    "${THIRD_PARTY_ROOT}/Win-VS2022")

But the results are the same. It almost seems like it’s returning every possible folder under THIRD_PARTY_ROOT.

Can someone help me understand what I’m doing incorrectly?

What Version
Cmake 3.23.1
OS Windows 11

I would try to filter with list(FILTER ... REGEX) as post step:

list(FILTER VS2022_FOLDERS INCLUDE REGEX [=[.*/Win-VS2022/.*]=])

Thank you @ClausKlein. That suggestion will certainly work. However, I see that more as a work around.

Perhaps I misunderstand the documentation, but I’m looking for the pattern that would do what I requested. From what I’ve read the results should only contains the pattern and it contains much more than that.

Although, maybe, LIST_DIRECTORIES, will list all of the files that match the pattern and then simply all of the directories too?

The GLOB_RECURSE mode will traverse all the subdirectories of the matched directory and match the files.

Since CMake version 3.3: By default GLOB_RECURSE omits directories from result list. Setting LIST_DIRECTORIES to true adds directories to result list. If FOLLOW_SYMLINKS is given or policy CMP0009 is not set to NEW then LIST_DIRECTORIES treats symlinks as directories.

Hello @ClausKlein,

When you say

Setting LIST_DIRECTORIES to true adds directories to result list

Do you mean that all directories found are added to the result list, or should it be just the directories that match the pattern?

I think you’re implying all directories are show and that the pattern match is only for files.

That was quoted from the documentation.
It search file names that match the globing expression!

file(GLOB_RECURSE folders LIST_DIRECTORIES YES
     RELATIVE ${PROJECT_SOURCE_DIR}/include/asio/experimental
       "include/asio/experimental/detail"
  )
  foreach(header IN LISTS folders)
    message("${header}")
  endforeach()

results in on unix:

detail
detail/impl
impl

and this

  file(GLOB_RECURSE folders LIST_DIRECTORIES YES 
       RELATIVE ${PROJECT_SOURCE_DIR}/include/asio # /experimental
       "include/asio/*/detail"
  )
detail/impl
execution/impl
experimental/detail
experimental/detail/impl
experimental/impl
generic/detail
generic/detail/impl
ip/detail
ip/detail/impl
ip/impl
local/detail
local/detail/impl
ssl/detail
ssl/detail/impl
ssl/impl

And past but not least:

  file(GLOB_RECURSE folders LIST_DIRECTORIES YES #
       RELATIVE ${PROJECT_SOURCE_DIR}/include/asio # /experimental
       "include/asio/*/detail/*.hpp"
  )

results in

experimental/detail/channel_handler.hpp
experimental/detail/channel_message.hpp
experimental/detail/channel_operation.hpp
experimental/detail/channel_payload.hpp
experimental/detail/channel_receive_op.hpp
experimental/detail/channel_send_functions.hpp
experimental/detail/channel_send_op.hpp
experimental/detail/channel_service.hpp
experimental/detail/coro_completion_handler.hpp
experimental/detail/coro_promise_allocator.hpp
experimental/detail/has_signature.hpp
experimental/detail/impl
experimental/detail/impl/channel_service.hpp
experimental/detail/partial_promise.hpp
generic/detail/endpoint.hpp
generic/detail/impl
ip/detail/endpoint.hpp
ip/detail/impl
ip/detail/socket_option.hpp
local/detail/endpoint.hpp
local/detail/impl
ssl/detail/buffered_handshake_op.hpp
ssl/detail/engine.hpp
ssl/detail/handshake_op.hpp
ssl/detail/impl
ssl/detail/io.hpp
ssl/detail/openssl_init.hpp
ssl/detail/openssl_types.hpp
ssl/detail/password_callback.hpp
ssl/detail/read_op.hpp
ssl/detail/shutdown_op.hpp
ssl/detail/stream_core.hpp
ssl/detail/verify_callback.hpp
ssl/detail/write_op.hpp

works fine for me :cowboy_hat_face: