18

How would a Bash (or other POSIX shell) command like this have to be expressed in fish?

ls -l $(which vim) # or
ls -l `which vim`

3 Answers 3

23

In fish, $ is used only for variable expansion. Omit the $ from the command and you should be good. Say:

ls -l (which vim)

You might also want to refer to the documentation: Command Substitutions

3
  • 1
    and this one: $(npm bin)/cowsay hello ?
    – Yukulélé
    Commented Jan 11, 2020 at 22:12
  • 2
    @Yukulélé npm=(npm bin) $npm/cowsay hello Commented Nov 17, 2020 at 23:31
  • Or eval "$(npm bin)"/cowsay hello Commented Jul 14, 2023 at 15:41
1

As of Fish version 3.4.0, command substitution may now be done with either $() or () grouping. E.g.:

ls -l $(which vim) # or
ls -l (which vim)

For versions prior to 3.4.0, only the () form is available.

Backticks, which do work in Bash and other POSIX shells, are not available as a command substitution operator. In general, backticks are no longer recommended in any shell for this purpose, but some habits (and old documentation) are hard to break.

3
  • 1
    Both notations are not supported (fish 3.6.1) when we want to start with it eg. (which vim) --version -->>fish: command substitutions not allowed here
    – Mesco
    Commented Jul 27, 2023 at 10:22
  • 1
    True, that's not a valid use for command substitution. The result of a command substitution is essentially the text result (perhaps an oversimplification) which is then passed to another command. In the example above, which vim returns the path to vim as text that the ls -l command can then process. If want to actually evaluate the text results in the shell itself, you'd need to eval $(which vim) --version. However, that has exactly the same result as vim --version, so why would you want to do it in the first place? Commented Jul 27, 2023 at 12:10
  • 1
    Perhaps you are looking to override an alias? If that's the case, then you want command vim --version. That will make sure to call the command (rather than an alias or function). Commented Jul 27, 2023 at 12:11
0

Sometimes you need to use string split inside (), otherwise -lgio-2.0 -lgobject-2.0 -lglib-2.0 will be incorrectly interpreted by the compiler as "go find a library named gio-2.0 -lgobject-2.0 -lglib-2.0, with the spaces being part of its name".

To quote the official tutorial

Unlike other shells, fish does not split command substitutions on any whitespace (like spaces or tabs), only newlines. This can be an issue with commands like pkg-config that print what is meant to be multiple arguments on a single line. To split it on spaces too, use string split.

> printf '%s\n' (pkg-config --libs gio-2.0)
-lgio-2.0 -lgobject-2.0 -lglib-2.0
> printf '%s\n' (pkg-config --libs gio-2.0 | string split " ")
-lgio-2.0
-lgobject-2.0
-lglib-2.0 ```

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .