In foo.sh, I have some commands (or functions) split to multiple lines and added comments, for readability:

# foo.sh: print computer information

foo() {
    uname \
        -p `# processor arch` \
        -s `# os name` \
        -v `# os version`


What works

I can run it okay:

$ ./foo.sh
Darwin 123... (correct output)

What doesn't work

But if I source it with source or ., my shell reports the following error, although the command it self is successfully run with my specified arguments (-psv):

% . ./foo.sh
./foo.sh:2: command not found: #
./foo.sh:2: command not found: #
./foo.sh:2: command not found: #
Darwin 123... (correct output as before)

I wonder why this happens? And how do I fix it? Because my primary goal is to define some functions, source them, and call them in shell as I need. Thank you!

  • 1
    What is -p # supposed to do? Is this supposed to be a comment? Aug 30, 2021 at 21:17
  • 3
    Does this answer your question? Allowing comments in interactive zsh commands Aug 30, 2021 at 21:22
  • @ArkadiuszDrabczyk on the line -p `# processor arch` \`, -p` is the argument, the "`# processor arch`" quoted is comment, and "``" is multiline separator.
    – jackxujh
    Aug 30, 2021 at 22:49
  • Is `# ... ` some kind of zsh extension? In normal shell syntax that would be a command substitution (of a somewhat nonsensical command).
    – zwol
    Aug 31, 2021 at 13:51
  • 3
    @zwol It's regular POSIX code. OP's intent seems to be to add comments in between line continuations. Since this isn't directly supported, they're using this "hack" by including command substitutions that expand to nothing. Aug 31, 2021 at 14:55

1 Answer 1


By default, zsh only recognizes comments in scripts, not when running interactively. This should apply to sourced scripts, but in recent versions (I've reproduced this behavior in 5.8, but 5.4.2 accepts your code just fine), this also applies to some code that is parsed after loading, such as code inside command substitution. This is probably a bug.

Put setopt interactive_comments in your .zshrc to support comments when running interactively. This doesn't really have a downside: it means you have to quote # at the beginning of a word, but # rarely appears at the beginning of a word on a command line. (# within a word doesn't start a comment, so this doesn't affect the use of # as an extended_glob wildcard character or in parameter expansion.)

Alternatively (or in addition), add

setopt local_options interactive_comments

inside the function. Then the comments will work.

  • Thank you, Gilles. The most helpful part of your answer, in addition to explaining how # is interpreted in zsh, is that you directly pointed out the option to set local_options inside the function. Because I haven't worked with setopt before at all, it will take me much time to figure out how to set the option to affect this function only.
    – jackxujh
    Aug 30, 2021 at 23:02
  • A follow up is, inside the function, without setting interactive_comments, something like pwd # 123 will work, which won't with $ pwd # 123. How is this different from comments in the multiline command?
    – jackxujh
    Aug 30, 2021 at 23:04
  • 1
    That's not (fully) correct. Comments are recognised in files sourced from interactive shells. If not, you wouldn't be able to source any script or your ~/.zshrc. Here, it looks more like a bug. Aug 31, 2021 at 5:18
  • I also doubt setopt local_options interactive_comments inside a function would work as that affects the parsing and functions are parsed before they're run (including that setopt command). Aug 31, 2021 at 5:20
  • Actually a regression. It was fine in zsh 4.0.1 Aug 31, 2021 at 5:27

You must log in to answer this question.

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