Wildcard in bash.shellAliases

As a side question in Impure flakes and CPU temperatures some aspects have been answered already.

However, I have no explanation why the wildcard works in the first but does not work in the second assignment:

programs.bash.shellAliases = {
  sg = "sudo gedit $*";
  ce = "sudo cp $* /etc/nixos/configuration.nix";
};

From Aliases (Bash Reference Manual)

There is no mechanism for using arguments in the replacement text, as in csh . If arguments are needed, use a shell function (see Shell Functions) instead.

Use one of the *shellInit options.

1 Like

I’d wager $* doesn’t contain anything and since you don’t have set -u it resolves to an empty string, ending up with just the args you gave the alias. So you could probably remove the $* and it’d work just fine.

Shell scripting languages are the epitome of writing arcane runes and hoping they do what you think they do.

1 Like

Thanks. Would you mind posting an example since

programs.bash.shellInit = {
  sg = "sudo gedit $*";
  ce = "sudo cp $* /etc/nixos/configuration.nix";
};

does not work and hard to find.

shellInit wants strings, according to the documentation link above. So something like

programs.bash.shellInit = ''
  alias sg="sudo gedit $*"
  alias ce="sudo cp $* /etc/nixos/configuration.nix"
'';

should do.

1 Like

You’ll actually need a shell function, like the docs say:

programs.bash = {
  shellAliases.sg = "sudo gedit";
  shellInit = ''
    function ce() {
      sudo cp $1 /etc/nixos/configuration.nix
    }
  '';
};
2 Likes

Ah, correct. Sorry, i just blindly copied the snippet and fixed the type error

actually y’all need fish :smiley:

abbr

1 Like

Interestingly
shellAliases.xd = "xxdiff $1 $2";
works w/o declaring it as a function which is surprising.

That’s again because the variables $1 and $2 are empty and bash just silently replaces them with empty strings.

So when you type:

xd file1 file2

Bash resolves this as:

xxdiff $1 $2 file1 file2

And then substitutes the variables with empty strings:

xxdiff   file1 file2

Since repeat empty spaces are still just treated as separators, the command works fine, it just has some odd superfluous whitespace.

It’d only break if you used that alias in a funtion that does have some args set, or if you explicitly set some really bad variable names for some reason.

Either way, you should probably switch to setting alias xd=xxdiff.

Or better yet, I’m with @bme here, switch to fish, nushell & co. These old shells aren’t designed with the principle of least surprise in mind. I mean, I clearly know exactly how to parse a large subset of stupid bash behavior and I still switched to nushell precisely because I don’t want the occasional brainfart to cause problems.

1 Like

Well put. I am going to switch to nushell, too. Appreciate the hint.

(edit)
An example how to set is as login shell would be useful. Thanks.

NixOS doesn’t have support for nushell as login, but I wouldn’t worry about that. A pretty normal thing to do (with the broadest compatibility) is to keep your login shell as bash, and set your terminal emulator to exec your preferred shell as interactive.

Even though NixOS for instance has fish support for login shell via programs.fish.enable I don’t use it, I have bash as login shell, I use home manager to manage session level environment variables in bash and nothing else, and exec fish -i (or the moral equivalent nix expression) in my terminal config. This way whatever weird arcane bash shit someone wants to source on login works and I don’t have to pray that babelfish / foreignenv are working properly. If I enter a nix shell (rather than using the direnv integration) the shell hooks all work correctly etc.

I’m not saying this is the only way to do it, but I think it has reasonable tradeoffs.

EDIT: I realise this is quite off topic, so if mods want to split the thread I wouldnt be sad.

2 Likes

Well explained. I will open a new thread when I get to it.

nu . reports “Could not read file” for me.

Have you tried just nu?

just tested but does not work for me: command not for for ce. Another reason to switch.

Yes, that works awesome. Thanks.

Fair enough! Even if you switch, for posterity’s sake, to figure out what’s going wrong you’d need to trawl through the exact stack of shell init file evaluations to figure out which rcfile actually gets these strings, and then figure out from there why it doesn’t propagate to your user shell. It’s quite possible that ends up only in login/non-interactive shells or such.

IMO these things shouldn’t be set up with system-wide config anyway and belong in your personal .bashrc, which you’d configure with home-manager.

2 Likes