I am very used to typing in a shell something like:

emacsclient **/Threshold.java

Where Threshold.java is a file deeply nested in a directory and I just want to open it by name.

When I try the same thing in eshell, I get (ec is an alias for find-file):

ec **/Threshold.java
Wrong type argument: stringp, ("src/main/java/org/elasticsearch/shield/admin/Threshold.java")

How can I get this working in eshell?

(defun eshell/my-find-file (pattern)
  (mapc #'find-file (mapcar #'expand-file-name pattern)))

then use my-find-file **/Threshold.java from Eshell, if you also want my-find-file to support non-glob pattern (for example, my-find-file Threshold.java), try following:

(defun eshell/my-find-file (pattern)
  (if (stringp pattern)
      (find-file pattern)
    (mapc #'find-file (mapcar #'expand-file-name pattern))))

Try this:

mapcar #'find-file **/Threshold.java

This only works if **/Threshold.java expands to exactly one file. Otherwise, the second file will be opened through a relative path, but based on the directory of the first file instead of the directory where the command was executed.

  • The key is that for eshell the wildcard becomes double *
    – Yu Shen
    Feb 20 '19 at 18:41

I wrote this handy function:

(defun eshell/for-each (cmd &rest args)
    (let ((fn (intern cmd))
          (dir default-directory))
      (dolist (arg (eshell-flatten-list args))
        (let ((default-directory dir))
          (funcall fn arg)))))

Notice the directory handling. You can then call, for example, for-each find-file **/Threshold.java OtherFileToo.java.

To open files from eshell I use this: alias ff for-each find-file $*.

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.