{ base, convert ? name: value: value, recursive ? false }: let scan = sub: let all = builtins.readDir (base + "/${builtins.concatStringsSep "/" sub}"); names = filter: builtins.filter filter (builtins.attrNames all); nix = name: all.${name} == "regular" && builtins.stringLength name > 4 && builtins.substring (builtins.stringLength name - 4) 4 name == ".nix"; dir = name: all.${name} == "directory"; files = map (name: sub ++ [ (builtins.substring 0 (builtins.stringLength name - 4) name) ]) (names nix); dirs = builtins.concatLists (map (name: scan (sub ++ [name])) (names dir)); in if recursive then files ++ dirs else files; root = scan []; item = relative: let name = builtins.concatStringsSep "/" relative; absolute = base + "/${name}.nix"; content = import absolute; value = convert name content; in { inherit name value; }; items = map item root; in if builtins.pathExists base then builtins.listToAttrs (map item root) else {}