How to (doubly-?) escape $*

I have a flake.nix that won’t build because of the following code:

          wrapper = pkgs.writeShellApplication {
            name = "wrapper";
            runtimeInputs = [ pkgs.mustache-go wombat-themer assets recurse-yaml ];
            text =
              ''
                wombat-themer ''$*
              '';
          };

The problem seems to be with the line wombat-themer ''$* The error message I get is

❯ nix build
warning: Git tree '/home/amy/codeberg/wombat-themer.NEW' is dirty
error: builder for '/nix/store/mak3918si9772j71ms1bll71r4grqkmv-wrapper.drv' failed with exit code 1;
       last 12 log lines:
       >
       > In /nix/store/gf0fmvah774d67vwshnphrr1cqm5hi0n-wrapper/bin/wrapper line 8:
       > wombat-themer $*
       >               ^-- SC2048 (warning): Use "$@" (with quotes) to prevent whitespace problems.
       >               ^-- SC2086 (info): Double quote to prevent globbing and word splitting.
       >
       > Did you mean:
       > wombat-themer "$*"
       >
       > For more information:
       >   https://www.shellcheck.net/wiki/SC2048 -- Use "$@" (with quotes) to prevent...
       >   https://www.shellcheck.net/wiki/SC2086 -- Double quote to prevent globbing ...
       For full logs, run:
         nix log /nix/store/mak3918si9772j71ms1bll71r4grqkmv-wrapper.drv

I’m able to replicate the problem in the REPL. First I checked to make sure that I was escaping the $ properly.

❯ nix repl
Nix 2.28.5
Type :? for help.
nix-repl> s = ''
            wombat-themer ''$*
          ''

nix-repl> s
"wombat-themer $*\n"

So far so good; the string is correct. So now to use it in writeShellApplication.

nix-repl> :l <nixpkgs>
Added 25694 variables.

nix-repl> d = writeShellApplication { name = "x"; text = s; }

nix-repl> :b d
error: builder for '/nix/store/bd14h16972fwcsa9phbwhgz0b9sfr002-x.drv' failed with exit code 1;
       last 12 log lines:
       >
       > In /nix/store/85x1k7488mh7q9v9888ciknn4pwz76yb-x/bin/x line 6:
       > wombat-themer $*
       >               ^-- SC2048 (warning): Use "$@" (with quotes) to prevent whitespace problems.
       >               ^-- SC2086 (info): Double quote to prevent globbing and word splitting.
       >
       > Did you mean: 
       > wombat-themer "$*"
       >
       > For more information:
       >   https://www.shellcheck.net/wiki/SC2048 -- Use "$@" (with quotes) to prevent...
       >   https://www.shellcheck.net/wiki/SC2086 -- Double quote to prevent globbing ...
       For full logs, run:
         nix log /nix/store/bd14h16972fwcsa9phbwhgz0b9sfr002-x.drv
[0 built (1 failed), 1 copied (7.4 MiB), 1.1 MiB DL]

I suspect what’s happening is that writeShellApplication is parsing the string that contains the $* a second time. at which point it’s not properly escaped. I did read the two links, and experimented with using $@ instead, but I don’t think I did it right because I get similar errors. How can I properly protect the $*?

This isn’t an error exactly, but a ShellCheck suggestion (and writeShellApplication, for better or for worse, treats all ShellCheck suggestions as errors). You’ve escaped the $ correctly as far as Nix is concerned (though it actually isn’t necessary!), and there is no double-parsing happening. You just need to satisfy ShellCheck by having the final script include quotes (or tell ShellCheck to ignore the ‘issue’, which I don’t want to nudge you into doing but is an option).

My recommendation is this:

            text =
              ''
                wombat-themer "$@"
              '';
1 Like