42

In my Makefile I need to get a list of all directories present in some other directory.

To get a list of all directories in the same folder as my Makefile I use:

DIRECTORIES = $(wildcard */)

all:
    echo $(DIRECTORIES)

which works fine, and gives me the desired list. However if I want to have a list of all directories in another directory using

DIRECTORIES = $(wildcard ../Test/*/)

all:
    echo $(DIRECTORIES)

I get a list of ALL files (with paths) in that directory, including .h and .cpp files.

Any suggestions why this happens and how to fix it? Other solutions to obtain the list are also welcome.

tremoloqui
  • 3,198
  • 3
  • 25
  • 22
Haatschii
  • 9,021
  • 10
  • 58
  • 95

3 Answers3

52

Use sort and dir functions together with wildcard:

DIRECTORY = $(sort $(dir $(wildcard ../Test/*/)))

From GNU make manual:

$(dir names...) Extracts the directory-part of each file name in names. The directory-part of the file name is everything up through (and including) the last slash in it. If the file name contains no slash, the directory part is the string ‘./’.

$(sort list) Sorts the words of list in lexical order, removing duplicate words. The output is a list of words separated by single spaces.

Also look at the second and the third method in this article: Automatically Creating a List of Directories

Lei Mou
  • 2,562
  • 1
  • 21
  • 29
  • 8
    This seems unnecessarily complex to me. I don't know why you need to `sort` for example. You can use: `$(dir $(wildcard ../Test/*/.))` (note adding the the `.` at the end to ensure that the final character is not a slash) and it will work everywhere. – MadScientist Feb 23 '17 at 17:39
  • 2
    @MadScientist, the `sort` ensures that the directories are traversed in alphabetical order. This is useful if you want to be able to tell at a glance how far the build has proceeded, for instance. When I omitted it, I found that on Windows, the directories were traversed in alphabetical order, but on Linux, they weren't. – Alan Dec 22 '17 at 16:51
  • 1
    @MadScientist Follow your advice and `.` does not get rid of the trailing slash, but it removes the current directory from the list. – fytao Oct 09 '20 at 08:02
  • Sorry I didn't understand your comment. – MadScientist Oct 09 '20 at 12:37
19

Try:

$(shell find <directory> -maxdepth 1 -type d)

which will give you the list of directories inside a given directory without going into subdirectories. You may need to clean that list up since it will include . and ./ before every directory listed.

kenorb
  • 155,785
  • 88
  • 678
  • 743
regulatethis
  • 2,322
  • 14
  • 17
7

Use:

$(wildcard ../Test/*/.)

This works fine.

Lee Mac
  • 15,615
  • 6
  • 32
  • 80
yuanjianpeng
  • 318
  • 2
  • 11
  • Why does this work? FWIW, it _does_ work but each directory entry will look like `path/to/dir/.`. So `cd` or `make -C` to `.` in some dirent does work, but it looks a little weird if you're printing progress info and you see it in the console, like I had been doing. Couple with `dir` to remove, like `$(dir $(wildcard ../Test/*/.))` – sherrellbc Feb 19 '21 at 23:19
  • every directory has two virtual child named `.` and `..` , `.` for current directory, `..` for parent directory, other type of child (regular file, symbolic file, char device etc) don't have child, so the above path filter files out. only directories matched. @sherrellbc – yuanjianpeng Nov 07 '22 at 02:35