Leonid Shifrin's implementation of a trieimplementation of a trie can be used for this purpose. It is available both for lists and for associations. For associations:
ClearAll[makeTreeAssoc];
makeTreeAssoc[wrds : {__String}] := Association@makeTreeAssoc[FileNameSplit /@ wrds];
makeTreeAssoc[wrds_ /; MemberQ[wrds, {}]] := makeTreeAssoc[DeleteCases[wrds, {}]];
makeTreeAssoc[wrds_] := Reap[If[# =!= {}, Sow[Rest[#], First@#]] & /@ wrds, _, #1 -> Association@makeTreeAssoc[#2] &][[2]]
Now you can do
tree[dir_] := makeTreeAssoc[FileNames["*", dir, 2]]
myTree = First@tree[$UserBaseDirectory]
Since the directory/file names are used as keys, I don't think there is a way to differentiate the files from the directories in the structure. You would have to check what it is upon retrieval.
OK so now we have to be able to go back to that other format too... I ended up with this
goBack[tree_, path_] := (
Sow[path];
If[Keys[tree] =!= {}, goBack[
tree[#],
Append[path, #]
] & /@ Keys[tree]]
)
len = Length@FileNameSplit[$UserBaseDirectory];
Select[
Reap[goBack[myTree, {}]][[2, 1]],
Length[#] >= len &
]