Code example below shows the problem:

bash -c "$(echo 'ls | wc -l')" # Working
"$(echo 'ls | wc -l')"         # Not working
$(echo 'ls | wc -l')           # Not working
'ls | wc -l'                   # Not working
'ls'                           # Working
ls | wc -l                     # Obviously working

What am I missing here?


If you give the shell a text string to execute, it will be able to do so if it happens to correspond to a command, like "ls" ("ls -l" is not the name of a command).

  • Your first example works because the echo in the command execution is executed by the invoking shell, generating bash -c "ls | wc -l". The pipeline is then executed by bash -c, which is fine.

  • The second, third and fourth example doesn't work since an extra step of evaluation needs to happen on the generated text string ls | wc -l. eval would do this for you.

The reason "ls -l" or "ls | wc -l" does not work is that quote removal happens after word splitting in the evaluation of the command line.

The reason $(echo 'ls | wc -l') doesn't work is that command substitution also happens after word splitting.

  • So, executing such string through bash/sh/zsh/whatever is the only available option? – Denis Sheremet Apr 24 '17 at 4:43
  • 1
    @DenisSheremet No, your could also use the built-in command eval. I did mentioned this. eval "ls | wc -l". – Kusalananda Apr 24 '17 at 6:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.