Currently we have a (not very efficient, but still) function FileNames
allowing to get the complete listing of all files and subdirectories of a directory at arbitrary depth. But it has no option allowing to restrict its output to the actual files when directories should be excluded. Hence for selecting only files from its output we are forced to use DirectoryQ
, FileType
or undocumented FileInformation
, all of them don't accept a list as an argument and add significant time to FileNames
:
FileNames[All, $InstallationDirectory, Infinity]; // AbsoluteTiming
FileNames[All, $InstallationDirectory, Infinity]; // AbsoluteTiming
l1 = Select[FileNames[All, $InstallationDirectory, Infinity],
Not@*DirectoryQ]; // AbsoluteTiming
l2 = Select[FileNames[All, $InstallationDirectory, Infinity],
FileType[#] === File &]; // AbsoluteTiming
l3 = Select[FileNames[All, $InstallationDirectory, Infinity],
FileInformation[#, "FileType"] === "File" &]; // AbsoluteTiming
l4 = Select[FileNames[All, $InstallationDirectory, Infinity],
Information[File@#, "FileType"] === "File" &]; // AbsoluteTiming
l1 == l2 == l3 == l4
{7.1199, Null} {6.98109, Null} {12.113, Null} {22.7185, Null} {20.8688, Null} {397.981, Null} True
Is there a more efficient way to obtain the complete listing of only actual files in a directory and its subdirectories at arbitrary depth?
P.S. There are other methods, but unfortunately they don't work in the latest Methamatica versions:
FileNames[name__ /; ! DirectoryQ[name], $InstallationDirectory, Infinity]
FileNames[StringExpression[
name__ /; Not[DirectoryQ[name]]], $InstallationDirectory, Infinity]
both return a list containing directories with Mathematica 13.0.0. With version 8.0.4 they work as expected, but slower than the l1
method above.
Keys@FileSystemMap[# &, $InstallationDirectory, Infinity, 1]
but it is slower for me than to useFileNames
. $\endgroup$