1

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?

5
  • 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
    Commented Dec 10, 2017 at 19:49
  • 2
    Please provide a more informative title for your post.
    – Dan
    Commented Dec 10, 2017 at 19:52
  • A couple of input-output examples could also prove very helpful.
    – Basil
    Commented Dec 10, 2017 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
    Commented Dec 10, 2017 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
    Commented Dec 10, 2017 at 20:38

1 Answer 1

2

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))))
        relparent)
    (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 and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.