Reputation: 14619
I'd like to walk a tree and end up with a list with a maximum of one file from each directory. The only criteria for the selected files are that they match a glob/pattern, for example "*.txt
".
In case it's not already implicit I need the algorithm to return stable results.
e.g. Given a tree that looks like this:
a/some/entry/foo.html
a/some/entry/foo.txt
a/some/entry/bar.txt
a/some/entry/baz.txt
a/some/entry/baz.bmp
a/some/boo.bat
a/some/boo.txt
a/some/bat.txt
a/other/path/far.txt
a/other/path/faz.txt
One acceptable result would be:
"a/some/entry/bar.txt a/other/path/far.txt a/some/boo.txt"
It seems like GLOB_RECURSE
and find_file
aren't appropriate for this task, so is there another approach that I should consider?
Upvotes: 0
Views: 2048
Reputation: 65981
The list returned by file (GLOB_RECURSE ...
is a superset of the desired result. Thus one possible solution is to post process the returned list by only selecting the first match returned for each directory.
The following CMake function sketches the necessary steps:
function (glob_recurse_first _globbingExpression _resultVar)
file (GLOB_RECURSE _pathList "${_globbingExpression}")
# canonical order
list (SORT _pathList)
# filter first match from each directory
set (_firstMatched "")
set (_latestDir "//")
foreach (_path IN LISTS _pathList)
get_filename_component(_dir "${_path}" DIRECTORY)
if (NOT "${_dir}" STREQUAL "${_latestDir}")
list (APPEND _firstMatched "${_path}")
set (_latestDir "${_dir}")
endif()
endforeach()
set (${_resultVar} ${_firstMatched} PARENT_SCOPE)
endfunction()
The function can be used in the following way:
glob_recurse_first("a/*.txt" _fileList)
foreach (_file ${_fileList})
message (STATUS "${_file}")
endforeach()
The globbing expression "a/*.txt"
will honor all files with the extension .txt
in directory a
and all its sub-directories.
The result variable _fileList
contains absolute paths with one file per sub-directory in a
.
Upvotes: 2
Reputation: 4549
I am not sure but you can create an executable file for searching directories by a command
$ grep -R version | awk -F: '/CMake.*:/ {print $1}'
like this example
https://unix.stackexchange.com/a/105342
and you can save this result to a new file and include this file if you need futher development
https://stackoverflow.com/a/17655165/914284
Upvotes: 1
Reputation: 3968
SET(resultfilelist "")
FILE(GLOB_RECURSE children LIST_DIRECTORIES true "${CMAKE_CURRENT_SOURCE_DIR}/a/*")
FOREACH(child ${children})
IF(IS_DIRECTORY ${child})
#message("Processing ${child}")
FILE(GLOB txtfiles LIST_DIRECTORIES false ${child}/*.txt)
list(LENGTH txtfiles txtfilessize)
IF(${txtfilessize} GREATER 0)
list(GET txtfiles 0 txtfilesfirst)
#message("Text file is ${txtfilesfirst}")
LIST(APPEND resultfilelist ${txtfilesfirst})
ENDIF()
ENDIF()
ENDFOREACH()
FOREACH(child ${resultfilelist})
message("Text file is ${child}")
ENDFOREACH()
Upvotes: 1