In Elisp, how to get path string with slash properly inserted?

后端 未结 6 659
闹比i
闹比i 2021-01-02 05:46

I am manually constructing path strings in Elisp by concatenating partial paths and directory names. Unfortunately sometimes the paths end with slash, sometimes not. Theref

相关标签:
6条回答
  • 2021-01-02 06:20

    If you deal with file manipulation, joining and splitting filepaths, checking empty directories and such, I strongly recommend installing f.el, modern file manipulation library. You will have a huge set of file and filepath manipulation functions under one namespace and will never reinvent the wheel again.

    The function you need is f-join, it concatenates parts of a path, adding slash only where needed.

    0 讨论(0)
  • 2021-01-02 06:23

    Unless you really care about keeping relative file names as relative, then it's always much better to avoid concat and use expand-file-name instead.

    0 讨论(0)
  • 2021-01-02 06:30

    Something like this should work as a starting point, although you'd want to flesh it out a bit to make it platform independent, etc.

    (defun append-path-component (path new-part)
      (if (string-match ".*/$" path)
        (concat path new-part)
        (concat path "/" new-part)))
    

    As per usual, there's probably some bit of elisp that already does this that I'm just not aware of.

    0 讨论(0)
  • 2021-01-02 06:31

    The easiest way to assemble file names from parts of questionable content is with expand-file-name. For example:

    (expand-file-name "foo.txt")
    

    this common form will give you a full file name based on default-directory:

    /home/me/foo.txt
    

    but if you have a variable 'dir' whose content is "/home/them/subdir" and want to use that, do this:

    (expand-file-name "foo.txt" dir)
    

    it doesn't matter if dir ends in / or not. If you are on some other platform, and contains the other slash, it will do the right thing then too. Do you have a mix? Just stack them:

    (expand-file-name "foo.txt" (expand-file-name "somesubdir" dir))
    
    0 讨论(0)
  • 2021-01-02 06:31
    (defun* tofilename (directorylist &optional (filename nil))
      "concatenate directory names into a path, with an optional file name as last part"
      (concat
       (mapconcat 'directory-file-name directorylist "/")
       "/"
       filename))
    
    
    (tofilename '("~/" "Temp/") "temp.txt")
    ;; => "~/Temp/temp.txt"
    
    (tofilename '("~/" "Temp/"))
    ;; => "~/Temp/"
    
    (tofilename '("~/" "Temp/" "test"))
    ;; => "~/Temp/temp/"
    
    0 讨论(0)
  • 2021-01-02 06:44

    (file-name-as-directory dir) will return directory path dir with a trailing slash, adding one if necessary, and not otherwise.

    If you had your sequence of partial paths in a list, you could do something like:

    (let ((directory-list '("/foo" "bar/" "p/q/" "x/y"))
          (file-name "some_file.el"))
      (concat
       (mapconcat 'file-name-as-directory directory-list "")
       file-name))
    
    "/foo/bar/p/q/x/y/some_file.el"
    

    or as an alternative, if you wanted to include the file name in the list, you could utilise directory-file-name which does the opposite of file-name-as-directory:

    (let ((path-list '("/foo" "bar/" "p/q/" "x/y/some_file.el")))
      (mapconcat 'directory-file-name path-list "/"))
    
    "/foo/bar/p/q/x/y/some_file.el"
    

    (Someone please correct me if using directory-file-name on a non-directory is not portable?)

    0 讨论(0)
提交回复
热议问题