How: pkgs.substituteAll + (chmod +x) + buildEnv?

Hi,

I have a directory of scripts next to a nix file. The scripts all end in .sh.

I want to run pkgs.substituteAll on each script and then buildEnv across all of those paths to get a bin directory of the scripts, after interpolation.

This is what I have so far:

let
  # this is close, but:
  # the writeScriptBin feels extra
  # this doesn't make the original substituted copied file executable
  # so this still doesn't actually work
  replaceScript =
    let
      s = (name: options: pkgs.substituteAll ({
        src = ./scripts + "/${name}";
      } // options));
    in name: options:
      pkgs.writeScriptBin "${name}" ''
        "${(s name options)}
      '';

  # also not sure how to map
  scripts = (filterAttrs (name: _: hasSuffix ".sh" name)
    (builtins.readDir ./. +"/scripts"));
  #outs = genAttrs scripts replaceScript; 
  
  joined = name: options: pkgs.buildEnv {
    name = "${name}-scripts";
    # paths = outs;
    # since the outs/mapping over 'scripts' doesn't work
    # just manually call replaceScript to get it working at least...
    paths = [
      (replaceScript "boot-vm.sh" options)
      (replaceScript "upload-image.sh" options)
    ];
  };

Turns out pkgs.substituteAll has some extra functionality so pkgs.writeScript* isn’t needed even. So after some tinkering, this works:

let

  pkgs = import <nixpkgs> {};
  inherit (pkgs) lib;

  options = {
    foo = "foo";
    bar = "bar";
  };

  scripts = lib.mapAttrs (name: type: pkgs.substituteAll ({
    src = ./scripts + "/${name}";
    dir = "bin";
    isExecutable = true;
  } // options)) (builtins.readDir ./scripts);


  joined = pkgs.symlinkJoin {
    name = "scripts";
    paths = lib.attrValues scripts;
  };

in joined
5 Likes