# List all the directories under the current one

I feel like I am forgetting something obvious, and will remember or be ashamed as soon as an answer turns up. However, I cannot for the life of me get all of the directories in the current working directory. That is, given the following folder structure:

a
-c
b
-c


I would expect

FileNames["*",{"*"},Infinity]


to return

{"a","b","a/c","b/c"}


{"a/c","b/c"}


I tried playing around with Infinity in the typical Levels in Mathematica (such as {1} vs. 1), but MMA complains about syntax. For the above example, how can I view a complete list of subdirectories. I came up with the following, but it doesn't seem exactly elegant:

RecursiveDirectory[dir_] :=
Module[{allDirs, allDirsCheck = {}, tempDirs},
allDirs = Select[FileNames["*"], DirectoryQ[#] &];
While[allDirs != allDirsCheck,
allDirsCheck = allDirs;
tempDirs = Select[FileNames["*", allDirs], DirectoryQ[#] &];
allDirs = Union[allDirs, tempDirs]
];
allDirs
]


This function gives me:

In[30]:= RecursiveDirectory["*"]
Out[30]= {"a", "a\\c", "b", "b\\c"}


As expected. What is a nicer way of doing this?

Maybe something like

Select[FileNames["*", "", Infinity], DirectoryQ]

• Thanks Heike, I didn't think of trying an empty quote. I think I tried everything but that. And I knew the answer would be very simple too.... – tkott Feb 27 '12 at 21:05
• One may also use FileType instead of DirectoryQ. – Szabolcs Sep 15 '17 at 10:35

If I'm not mistaken the second asterisk in your line

FileNames["*",{"*"},Infinity]


should be replaced with the location of the directory you want to look in.

In case of the directory where your notebook lives in this would be:

FileNames["*", {NotebookDirectory[]}, Infinity]


or, for the current directory, this would be:

FileNames["*", {Directory[]}, Infinity]

• Thanks Sjoerd. +1 for a detailed answer, but according to MMA.SE, Heike answered first (post 2389 vs. 2390) – tkott Feb 27 '12 at 21:06
• @tkott This isn't a racing contest and please don't feel obliged to accept an answer the minute it arrives. That will discourage others to add their answers. – Sjoerd C. de Vries Feb 27 '12 at 21:24

I recommend an external command approach. On Windows this looks like this:

command = "!dir \"" <> Directory[] <> "\" /A:D /S /B";



This can be many times faster than the Select - FileNames method.

Select[
FileNames["*", "C:\\Data & Images", Infinity],
DirectoryQ
] // Length // AbsoluteTiming

{6.7413856, 5693}

command = "!dir \"" <> "C:\\Data & Images" <> "\" /A:D /S /B";
ReadList[command, String] // Length // AbsoluteTiming

{0.3900223, 5693}

• I use ReadList often but had never discovered this. Good stuff! +1 – Andy Ross Feb 28 '12 at 6:26
• @Andy thank you. I presume you mean the ability to read command line output? – Mr.Wizard Feb 28 '12 at 20:21
• Yes, that is what I was referring to. I had a vague idea about using command line input in other places, I didn't realize it worked here as well. Potentially a very powerful idea. – Andy Ross Feb 28 '12 at 20:25
• @Andy yes, it's surely cleaner than having to write to a temporary file, only to ReadList that. I think this should be better documented (present on the ReadList doc page). – Mr.Wizard Feb 28 '12 at 20:30
• You should file that as a suggestion to WRI if you haven't already. – Andy Ross Feb 28 '12 at 20:35

If one needs to list only non-empty directories, it can be easily achieved by applying DirectoryName to the output of FileNames. For example, listing all non-empty directories in $UserBaseDirectory up to the depth 2: DeleteDuplicates[DirectoryName /@ FileNames[All,$UserBaseDirectory, 2]]

{"C:\\Users\\user\\AppData\\Roaming\\Mathematica\\",
"C:\\Users\\user\\AppData\\Roaming\\Mathematica\\ApplicationData\\",
"C:\\Users\\user\\AppData\\Roaming\\Mathematica\\Applications\\",
"C:\\Users\\user\\AppData\\Roaming\\Mathematica\\FrontEnd\\",
"C:\\Users\\user\\AppData\\Roaming\\Mathematica\\Kernel\\",
"C:\\Users\\user\\AppData\\Roaming\\Mathematica\\Knowledgebase\\",
"C:\\Users\\user\\AppData\\Roaming\\Mathematica\\_MyStyleSheets_\\",
"C:\\Users\\user\\AppData\\Roaming\\Mathematica\\Paclets\\",
"C:\\Users\\user\\AppData\\Roaming\\Mathematica\\SystemFiles\\"}


An alternative is external command approach which allows to restrict the depth of recursion.

According to this answer, starting from Windows Vista we have the ROBOCOPY utility as a part of the system which allows to list all subdirectories (including empty):

With[{dir = $$UserBaseDirectory, depth = "2"}, StringTrim@ImportString[ RunProcess[{"robocopy", dir, dir, "/l", "/s", "/njh", "/njs", "/ns", "/lev:" <> depth}, "StandardOutput"], "Lines", CharacterEncoding ->$$SystemCharacterEncoding]]

{"C:\\Users\\user\\AppData\\Roaming\\Mathematica\\",
"C:\\Users\\user\\AppData\\Roaming\\Mathematica\\_MyStyleSheets_\\",
"C:\\Users\\user\\AppData\\Roaming\\Mathematica\\ApplicationData\\",
"C:\\Users\\user\\AppData\\Roaming\\Mathematica\\Applications\\",