Search code examples
fileelisp

Ensure filepath exists for reading


I need to define a function that will, without unnecessary side effects (i.e. an open buffer), ensure a file exists ready for reading.

Here is what I have so far:

(defun ensure-existence (file)
  (if (not (file-exists-p file))
    (kill-buffer
     (save-buffer
      (find-file-noselect file))))

which (seems to) work fine when the directory exists. Unfortunately, I can't be sure that this is the case (since variables may change, etc.). Is there any way to incorporate make-directory into all of this or, better yet, is there a cleaner solution?

My ideal use case would be something like this:

(ensure-existence "new/path/to/new/file.txt"
   (func1 arg1)
   (func2 arg2a arg2b)
   (...))

which would necessitate a signature like this:

(defun ensure-existence (file &rest body) ...)

but I don't really know how to do that. :/


This is all for a Stack Exchange mode for Emacs new link: sx.el, by the way :-)


Solution

  • As suggested by @Stefan,

    (defun ensure-file-exists (file)
      (unless (file-exist-p file)
        (make-directory (file-name-directory file) t)
        (write-region "" nil file nil 'silent)))
    

    This should work on both windows and unix.

    EDIT: actually, you can do away with the file existence check by passing the append t argument to write-region, but this would change the modification time of the file if it already exists (just like touch).

    Just for comparison, the Common Lisp version would look like this:

    (defun ensure-file-exists (file &key verbose)
      (ensure-directories-exist foo :verbose verbose)
      (open file :direction :probe :if-does-not-exist :create))
    

    (see open and ensure-file-exists).