For some reason it appears eshell/echo can't handle dashes:

$ echo "aaaaaaaaaaaaa"
$ echo "============="
$ echo "-------------"

Is this expected behavior? I assume it's interpreting the dashes as flags and the quote isn't helping inhibit that. Should I be escaping it a different way?

1 Answer 1


You can use -- to tell eshell not to interpret arguments that follow as command-line switches. This is the standard way of passing an argument (such as a file name) starting with a dash to GNU tools.

In summary: try

echo -- "-------------"

or just

echo -- -------------

(as far as I can tell all arguments are interpreted as strings).

There are two issues (I would even say bugs here):

  • eshell--process-args uses "^-\\(-\\)?\\(.*\\)" to match switches, i.e. anything starting with one or two dashes is treated as a switch and removed from the list of arguments. If we disallow switches starting with three dashes and use "^-\\(-\\)?\\([^-].*\\)", echo --- works as expected.

  • eshell--process-option has a bug that prevents it from printing an error message when an unrecognized switch is passed to an eshell command without an "external" equivalent.

See the code block below for the fixed version. (Note that (error ...) is outside (when extcmd ...).

(defun eshell--process-option (name switch kind ai options opt-vals)
  "For NAME, process SWITCH (of type KIND), from args at index AI.
    The SWITCH will be looked up in the set of OPTIONS.

    SWITCH should be either a string or character.  KIND should be the
    integer 0 if it's a character, or 1 if it's a string.

    The SWITCH is then be matched against OPTIONS.  If no matching handler
    is found, and an :external command is defined (and available), it will
    be called; otherwise, an error will be triggered to say that the
    switch is unrecognized."
  (let* ((opts options)
    (while opts
      (if (and (listp (car opts))
               (nth kind (car opts))
               (equal switch (nth kind (car opts))))
            (eshell--set-option name ai (car opts) options opt-vals)
            (setq found t opts nil))
        (setq opts (cdr opts))))
    (unless found
      (let ((extcmd (memq ':external options)))
        (when extcmd
          (setq extcmd (eshell-search-path (cadr extcmd)))
          (if extcmd
              (throw 'eshell-ext-command extcmd)))
        (error (if (characterp switch) "%s: unrecognized option -%c"
                 "%s: unrecognized option --%s")
               name switch)))))

PS: I'm using GNU Emacs 24.5.1.

  • This isn't really satisfactory as echo "---" in zsh does the right thing.
    – wasamasa
    Dec 11, 2015 at 21:04
  • @wasamasa: Well, that's what eshell does in Emacs 24.5.1. I think I know why; please see the updated answer. Dec 11, 2015 at 21:27
  • Thanks, this is already better, though I find it still concerning "---" is interpreted as invalid option and "--" is accepted silently.
    – wasamasa
    Dec 11, 2015 at 23:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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