I'm walking a directory tree upwards from default-directory in a loop, so I need a way to say "take the last component off this path that ends in a slash and return a result that ends in a slash". The closest built-in thing I found is (file-name-directory) and it's not a great fit. I ended up writing this:

(defun pop-dir (dir)
  "Pops a trailing directory off DIR to return the remainder of the path."
  (concat "/"
          ;; there's probably some better way to do this but ¯\_(ツ)_/¯
          (string-join (reverse (cdr (reverse (split-string dir "/" t)))) "/")

There has to be a better way; what is it?

  • I am I correct in understanding pop-dir should return the parent directory of its argument? If so, you can write (file-name-directory (directory-file-name FILENAME)) for any given FILENAME, regardless of whether it names a file or directory. – Basil Dec 10 '17 at 19:49
  • 2
    Please provide a more informative title for your post. – Dan Dec 10 '17 at 19:52
  • A couple of input-output examples could also prove very helpful. – Basil Dec 10 '17 at 19:59
  • 1
    As a general rule, you should use the functions that Emacs provides for manipulating file and directory names, not general string-manipulation functions such as concat. String functions really know nothing about files, directories, or their names. – Drew Dec 10 '17 at 20:35
  • What both @Basil and Dan said is important. State what you expect to use as input and what you would like to have as output, and put your summary request in the question title. Thx. – Drew Dec 10 '17 at 20:38

You say, "take the last component off [a] path that ends in a slash and return a result that ends in a slash".

Is this what you're looking for? This is from Dired+ (but it doesn't depend on anything from Dired+.)

(defun diredp-parent-dir (file &optional relativep)
  "Return the parent directory of FILE, or nil if none.
Optional arg RELATIVEP non-nil means return a relative name, that is,
just the parent component."
  (let ((parent  (file-name-directory (directory-file-name (expand-file-name file))))
    (when relativep (setq relparent  (file-name-nondirectory (directory-file-name parent))))
    (and (not (equal parent file))  (or relparent  parent))))

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.