Search code examples
shellterminalfish

fish shell command subsitution in watch command


I'm trying to use the watch command in the fish shell.

sudo watch -d "lsof -a -p (pidof myprogram)"

As you can see this valid command substitution syntax for fish. however I get the following error in watch when I run it.

sh: -c: line 0: syntax error near unexpected token '('
sh: -c: line 0: `lsof -a -p (pidof myprogram)'

If I change the command to sh compatible syntax

sudo watch -d "lsof -a -p $(pidof myprogram)"

I get the following error.

$(...) is not supported. In fish, please use '(pidof)'.                                                                                                                        
fish: sudo watch -d "lsof -a -p $(pidof myprogram)"

Is there a way around this?


Solution

  • In short:

    sudo watch -d "lsof -a -p "(pidof myprogram)
    

    I.e. exit the quotes and do the command substitution (without a space in-between, so it'll be directly attached).

    There's a bit of a gap in here in that you want the command's output to not be split at all - here it would split it on newline, and make multiple tokens like "lsof -a -p "line1 "lsof -a -p"line2. That shouldn't be an issue in this case, but if you want it, you should use string split0 like

     sudo watch -d "lsof -a -p "(pidof myprogram | string split0)
    

    which will only split on NULL-bytes, which aren't allowed in commandline arguments (this is a general unix thing - because arguments to main are passed as NULL-delimited strings without any other indication of length, if they contain NULLs they will be truncated).