Why doesn't systemctl\ {restart,status}\ sshd\; work?

It is a form of Brace expansion done in the shell. The brace-expansion idea is right, but the way it was used is incorrect here. When you meant to do:

systemctl\ {restart,status}\ sshd\;

The shell interprets systemctl restart sshd; as one long command and tries to run it, and it couldn't locate a binary to run it that way. Because at this stage, the shell tries to tokenize the items in the command line before building the complete command with arguments -- but it has not happened yet.

For such known expansion values, you could use eval and still be safe, but be sure of what you are trying to expand with it.

eval systemctl\ {restart,status}\ sshd\;

But I would rather use a loop instead with for, instead of trying to do write a one-liner or use eval:

for action in restart status; do
    systemctl "$action" sshd
done

This is called brace expansion (as the tag indicates).

What did I do wrong here? Why doesn't it work?

Consider the stages involved in reading and executing a command line in bash (for example):

  1. reads a line
  2. parses a possibly compound command into component simple commands
  3. does various expansions on the simple commands (brace expansion, word splitting, globbing, etc.)
  4. then executes the simple commands (with other stages omitted for clarity).

What you're trying to do is affect (2) from (3). The splitting based on ; is in stage (2), when it's parsing compound commands. By the time (3) is happening for brace expansion, it's already too late to try and create a compound command.


The first line

echo systemctl\ {restart,status}\ sshd\;

expand as 3 token

then echo echo the last two token, and it looks OK.

likewise the second line

systemctl\ {restart,status}\ sshd\;

expands as 2 tokens

and bash try to look for an executable systemctl restart sshd; which it couldn't find.

You might whish to begin your journey on dark side using eval systemctl\ {restart,status}\ sshd\; beware of the unexpected.