Is it possible from within Emacs to find directories with a given depth from the current directory from within Emacs and receive their respective location in form of a list? I want it to work cross platform...

4 Answers 4


I'd be inclined to use find for that:

(let ((dirname (expand-file-name "~/"))
      (depth 3))
    (format "find %s -mindepth %d -maxdepth %d -type d -print0 2>/dev/null"
            (shell-quote-argument dirname) depth depth))
   "\0" :omit-nulls))

n.b. -mindepth, -maxdepth, and print0 are not POSIX options, so YMMV regarding portability.

  • I know but find would not work across different platforms. Oct 23, 2018 at 9:54
  • @sidhartharya You didn't mention the requirement that the code should work across platforms in your question. Therefore, this answer is equally valid as the others. (That's why I up-voted it.) Furthermore, the gnu-find tool is available for several platforms. E.g., on Windows by mingw.
    – Tobias
    Oct 24, 2018 at 9:43
  • Yes gnu find is available across platforms but I want to do it , in a way, so the user doesn't have to explicitely install something specifically for that.. And also if i had to issue a shell command why would i ask it here. But thank's i will make the edit Oct 24, 2018 at 9:51

The elgrep-search command has options :mindepth and :maxdepth. Elgrep is available via package-install from the melpa package archive (instructions how to add melpa to package-archives can be found on the melpa "Getting Started" page).

You can use elgrep as follows to get a list of matching file names of a specific depth. In the example I search in my HOME-directory (~/) for files matching \.el\' without in-file matches (that's the nil) with minimal and maximal recursion depth 2.

(require 'elgrep)
(mapcar 'car (elgrep-search "~/" "\\.el\\'" nil :recursive t :mindepth 2 :maxdepth 2))

Elgrep actually returns filematches. That are conses of the file name and a list of in-file matches. In our case the list of in-file matches is empty since we passed nil for the in-file regexp. Because of that structure you need the (mapcar 'car ...). See the documentation of the elgrep-search command for further details.

Note, that mindepth and maxdepth are also available via the gui-version elgrep-menu. There you can let elgrep search asynchronously. That way it does not block your Emacs.


Library find-dired+.el can help with this. C-h f find-dired:

find-dired is an interactive compiled Lisp function in find-dired+.el.


Run find and put its output in a buffer in Dired Mode.

Then run find-dired-hook and dired-after-readin-hook.

The find’ command run (after changing intoDIR) is essentially this, whereLS-SWITCHESis(car find-ls-option)`:

 find . \( ARGS \) LS-SWITCHES

Optional args:

  • DEPTH-LIMITS: Minimum and maximum depths: (MIN-DEPTH MAX-DEPTH).
  • EXCLUDED-PATHS: Strings matching paths to be excluded. Uses find switch -path.

When both optional args are non-nil, the find command run is this:

find . -mindepth MIN-DEPTH -maxdepth MAX-DEPTH
     \( -path EXCLUDE1 -o -path EXCLUDE2 ... \)
     -prune -o \( ARGS \) LS-SWITCHES

where EXCLUDE1, EXCLUDE2... are the EXCLUDED-PATHS, but shell-quoted.

Same thing for the related commands: find-name-dired, find-grep-dired, and find-time-dired - they all take arg DEPTH-LIMITS.

To reply to @Tobias's comment: Yes, find-dired+.el (which extends standard library find-dired.el) depends on a UNIX or GNU/Linux find command. On MS Windows you can use Cygwin or any other porting of the command to Windows.

  • As I understand the code find-dired+.el uses the external find program. Therefore, the same comments as for Phils answer apply. Disclaimer: I had only a short glance on the code. It may be that you have some fallback there that uses emacs-internals when gnu-find is not available. I didn't check for that. Please correct me if that is the case.
    – Tobias
    Oct 24, 2018 at 9:46

You can use the ls command of the built-in eshell for listing the files with some predefined depth.

You have to specify the depth by the right number of concatenated file name generator expressions */.


  (eshell-command-result "ls /usr/share/emacs/26.1/*/*/*/*/*/*(.)")
 "\n" t)

The appended modifier (.) says that the generator only expands regular file paths.

Note that the backend eshell-do-ls command is a pure Emacs Lisp implementation of the ls command. Yet in this case the actual work is not done by ls but by eshell-glob.

If you also want to list directories you should add the -d switch to the ls command. Otherwise the files contained in the directories would also be listed:

  (eshell-command-result "ls -d /usr/share/emacs/26.1/*/*/*/*/*/*")
 "\n" t)

If you actually don't want any special features of ls you can also use pure eshell-extended-glob:

(eshell-extended-glob "/usr/share/emacs/26.1/*/*/*/*/*/*")

If you want to list all files with some minimal depths you can expand with the two-star form **, e.g.,

(eshell-extended-glob "/usr/share/emacs/26.1/*/*/*/**/*")
  • That's a great idea . Thank you so much. Oct 25, 2018 at 2:17

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.