How to use a wildcard in a path expression?

I’m using modules for my NixOS configuration files, and I created a folder for all my services where I have a .nix for each service defined. I’m trying to import these files in my NixOS configuration like this:

imports =
  [
    "./services/*.nix"
  ];

But I realize that this is not technically a path. Would it be possible to write some Nix code to add the paths matching the wildcard to the path set?

You’d have to use readDir and filterAttrs using a regex with builtins.match on the names.

I guess you could emulate wildcards using regex.

I think someone built an easier to use abstraction for this but I can’t remember the details.

1 Like

There is also lib.fileset which IIRC already allows returning lists (right @infinisil?). You can’t use wildcards there but it’s possible to define filters in the Nix language (which is more verbose but I find it easier to reason about since it’s not trying to mash multiple languages into each other).

I don’t think lib.fileset would work well here, because there’s no way to only filter files in a directory without recursing. You can only do ./services/**/*.nix using

{
  imports = lib.fileset.toList
    (lib.fileset.fileFilter (file: file.hasExt "nix") ./services);
}

That is a bit of a functionality hole in lib.fileset tbh (though this example is not a use case it was designed for).

2 Likes

All this seems complicated. Maybe there are some improvements to make it easier, especially if it is a recurring pattern.

I will list each of my files individually.

It’s fairly simple tbh, here’s a direct answer:

imports = lib.pipe ./services [
  builtins.readDir
  (lib.filterAttrs (name: _: lib.hasSuffix ".nix" name))
  (lib.mapAttrsToList (name: _: ./services + "/${name}"))
];
1 Like