33

Often, I know the file name but don't remember or find it cumbersome to specify the exactly directory. I'd like to be able to do:

find-file x/y/*/some_file.txt

where * would allow searching in recursive directories instead of just the current one.

2240
  • 1,547
  • 2
  • 12
  • 30
Vijay Kotari
  • 1,945
  • 3
  • 15
  • 16
  • 1
    Expansion of such path has two potential dangers: there may be more then one valid expansions, there may be too many paths to try (especially if there's a directory loop), so, probably, you'll have to just use something like `find-name-dired`. –  Sep 26 '13 at 23:46
  • helm-find is great if you use helm. helm-gtags-find-file is even better if you have helm-gtags installed. – Vasantha Ganesh Jul 20 '20 at 10:51

10 Answers10

39

As described here:

M-x find-name-dired

After you provide the directory and the pattern the matching files will be displayed in a Dired buffer. You can navigate the file list (C-n, C-p, etc.) and open files as you wish (Ret).

pink-potato
  • 491
  • 3
  • 4
11

I've long looked for that feature and I'm now satisfied with what I found: I'm using helm-projectile.

Projectile is a project interaction library. Projects are VCS directories or directories containing a .projectile file. It is based on GNU find (but offers a pure emacs lisp implementation too)

https://github.com/bbatsov/projectile

(you can install it with packages.el). You can use it alone: call projectile-find-file (or projectile-mode and C-c p f). It uses ido for the completion by default, but in that case I prefer the interface of helm-projectile.

My colleagues kept telling me to use Sublime Text because of that feature. Fortunately, I found projectile :)

Ehvince
  • 17,274
  • 7
  • 58
  • 79
  • Projectile is great. It's easy to use and straight forward. – gosukiwi Jul 19 '15 at 04:55
  • What I didn't find in `projectile` is an ability to find a couple of files and switch between them. E.g. if you want to inspect all the `.gitignore` files in a project. But nevertheless, a nice package. – x-yuri Nov 11 '21 at 01:06
7

ido-find-file does this: when the filename that you enter doesn't match anything in the current directory, it uses something like locate to match what you wrote against all files on your system.

The setup is just one line:

(ido-mode)

After this, C-x C-f will call ido-find-file. Also, I usually add:

(setq ido-enable-flex-matching t)

because I like it, but with it you will locate more results, i.e. foo will also match froo.

abo-abo
  • 20,038
  • 3
  • 50
  • 71
4

In case of files in a project directory, I have used Fiplr that uses a fuzzy search library by the same author.

https://github.com/d11wtq/fiplr

This is available from MELPA.

Other solution that I haven't tried is https://github.com/technomancy/find-file-in-project

mythicalcoder
  • 3,143
  • 1
  • 32
  • 42
user308879
  • 303
  • 1
  • 8
2

edit: I found much better with projectile, see my other answer.

There is find-recursive.el : http://www.webweavertech.com/ovidiu/emacs/find-recursive.txt

Download it, put it in your load path and require it in your .emacs: (it isn't available through ELPA or el-get)

(require 'find-recursive)      

now when you call M-x find-recursive, it will ask for a file name to search for recursively, a base directory, then you have to select one file among a result list. It isn't integrated into ido unfortunately, but I like it, it is useful sometimes.

Ehvince
  • 17,274
  • 7
  • 58
  • 79
2

Here is a solution that gives you selectivity over the files and subdirectories searched. To use it you need both Dired+ and Icicles.

The command, used only in Dired, is icicle-visit-marked-file-of-content-recursive (or the -other-window version of it). It is bound to M-+ C-F (for other window, use M-+ C-O -- and yes, those are uppercase F and O).

What it does:

  • It provides, as candidates for completion, all of the files marked in the current Dired directory, pslus all of those in any marked subdirectories that have Dired buffers, and so on recursively.

  • You can visit any number of such candidates that match your minibuffer input, including all of them. You can visit some that match a minibuffer input pattern, then change the pattern to match and visit others --- all in the same command invocation.

  • "Matching" your input can mean either or both:

    • Matching the file name
    • Matching the file content

    That is, your input can be two-part (separated by hitting C-M-j: a file-name part and a file-content part. Narrow the choices by matching file names, and narrow further by matching text in those files. This search is fast -- it succeeds as soon as it finds a single match in the file.

    You can omit either part: match only file names (fast) or only file contents (slower, naturally).

  • You can combine input patterns -- progressive completion. It is much easier to add additional patterns to match, incrementally and interactively, than it is to try to come up with a single regexp that does just what you want.

  • Each input pattern (each part of a two-part pattern) can be a regexp. Fuzzy matching is also available.

  • You can alternatively just insert subdirectories in your Dired buffer, instead of having them as separate Dired buffers. Any files and subdirs marked in a Dired buffer are handled the same way.

    If you do not want to descend into subdirs that are marked, you can use the non-recursive version of the command, icicle-visit-marked-file-of-content, bound to C-F (C-O for other-window).

If you also use Bookmark+ then you can bookmark a Dired buffer or a set of Dired buffers. The bookmark records which files and subdirectories are marked, which subdirectories are inserted, and which files and subdirectories are omitted. Jumping to such a bookmark restores all of these things. This gives you a way to snapshot a project, which you can then search using M-+ C-F etc.

Drew
  • 29,895
  • 7
  • 74
  • 104
1

A lot of options listed, I'm using next command:

find-file-in-current-directory

You can put it in your .emacs like this:

;; Find file in current directory:
(global-set-key (kbd "C-M-,") 'find-file-in-current-directory)

Interface looks very familiar to those who use fsf tools (https://github.com/junegunn/fzf)

wildneuro
  • 203
  • 2
  • 3
1

If you have helm, you can use this:

(defun my/helm-find-file-recursively ()
   "Recursively find files in glob manner, in the specified directory."
   (interactive)
   (helm-find 'ask-for-dir))

(global-set-key (kbd "C-c o f") 'my/helm-find-file-recursively)
Sami
  • 45
  • 6
0

Icicles command icicle-locate (or icicle-locate-file, if you do not have a locate program for your OS) is made for that. Locate a file anywhere under a given directory (including ~HOME or the root directory).

You can match against any parts of the absolute file name (i.e., the path and the file name). You can use several kinds of matching, including regexp, substring, and fuzzy matching.

Drew
  • 29,895
  • 7
  • 74
  • 104
0

For a more programmatic approach (using the built-in files library):

(directory-files-recursively "~/assignments/" "[0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}.org")

;; ("~/assignments/a/b/2022-05-18.org"
;;  "~/assignments/c/d/2022-07-15.org"
;;  "~/assignments/e/f/2022-08-08.org")

Here's a thin wrapper around that function which reads a filename from the minibuffer and returns a list of matching directories (starting from the current directory), from which you select an entry which will then be visited:

(defun my/find-directory ()
  "Find the directory containing FILE."
  (interactive)
  (let ((matches (directory-files-recursively default-directory (read-from-minibuffer "Filename: "))))
    (if matches
      (find-file
       (completing-read
    "Pick a directory: "
    (mapcar 'file-name-directory matches))))
    (message "No matching directories.")))
grtcdr
  • 45
  • 2
  • 7