In Bash, I have an alias of ls -Ap | grep --color=always /$ that grabs the directories of the current directory, more or less.

That said, using the same as an alias in Emacs's eShell seems to not work, at all.

It keeps grabbing files, as well, that (as far as I can tell) don't even have forward slashes anywhere in their names.

Does the forward slash mean something to eShell that it doesn't for Bash?

2 Answers 2


The problem seems to be something peculiar about how eshell interacts with ls, not grep.

I can confirm your example, which works fine in shell-mode or a terminal, produces long output in eshell, and includes files, not just directories. This is the same using the built-in versions of ls and grep, and also using the 'normal' versions from the operating system. That is, eshell provides its own versions of ls and grep, and if you want to use the regular versions you have to specify *ls and *grep.

For me, the output of your code, with the eshell or standard versions of the commands, produces output in columns. In normal use, ls outputs filenames in columns for interactive use, but one per line when used in a pipe. This convention isn't followed in eshell apparently. You can force the output to be one file per line with the -1 flag, :

ls -Ap1 | grep --color=always /$

I find these little edge cases pop up regularly with eshell. shell-mode doesn't include the elisp tools that eshell does, but I find it less surprising, and so easier to use.

  • Ahhh; I knew the commands were different but, from what I could see from the output, it didn't look like eShell's ls was providing anything Bash's ls wasn't. I'm so used to Bash showing the results in columns, every so often, that it didn't even occur to me that grep would read it that way, as well. Thanks for the explanation! It was really good at teasing out the points of misunderstanding.
    – Jaft
    Jan 17, 2019 at 20:05

eshell is not "bash in Emacs", it is its own shell. If you want to use "bash in Emacs" use shell-mode (M-x shell) instead and Emacs will run 'bash' (really, your default shell) as a sub-process. If you want to use eshell, you'll need to change your thinking a bit. Arguments that are expandable wildcards are passed to their command as an elisp list (a la ("a" "b" "c")) not a flat list (a b c). The easiest way to see this is to compare the results of echo * in bash and eshell.

bash$ mkdir foo; cd foo
bash$ touch a c; mkdir b d
bash$ echo *
a b c d

eshell$ mkdir bar; cd bar
eshell$ touch a c; mkdir b d
eshell$ echo *
("a" "b/" "c" "d/")

Since eshell is lisp we can use a predicate to change the meaning of the wild card. (In this case only directories)

eshell$ echo *(/)
("b/ "d/")

Now, about your alias in general. To "grab the directories of the current directory" I would instead use ls -d */.

bash$ ls -d */
b/ d/

eshell$ ls -d */
a b/ c d/
eshell$ ls -d *(/)
b/ d/
eshell$ ls -d *(^/)
a c

I highly recommend reading Mastering Eshell, Eshell Functions / Dealing With Wildcards and Multiple Files, and EshellAlias as they explain these aspects of eshell much more clearly than I can.

  • I hame some Qs regarding the Mastering Emacs page: it says the order of evaluation is:- 1 A full filepath (e.g. /bin/cp) runs cp in /bin 2 Look for the command prefix, eshell-explicit-command-char (default is *), and if it is found then look for the command in the search path. 3 Look for a shell-defined alias (alias command) 4 Look for cp in the search path, $PATH (or eshell-path-env) 5 Look for a Lisp function named cp or the elisp function eshell/cp: and I would say this is way wrong. Surely 4 & 5 are reversed?
    – RichieHH
    Jan 9, 2020 at 8:05

Your Answer

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

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