Tôi đang xây dựng chuỗi đường dẫn theo cách thủ công trong Elisp bằng cách nối các đường dẫn một phần và tên thư mục. Thật không may đôi khi các con đường kết thúc bằng dấu gạch chéo, đôi khi không. Vì vậy, tôi cần phải chèn dấu gạch chéo trước khi ghép một tên thư mục khi cần thiết nhưng không phải khác. Cách tốt để làm điều này là gì?Trong Elisp, làm thế nào để có được chuỗi đường dẫn với dấu gạch chéo được chèn đúng cách?
Trả lời
(file-name-as-directory dir)
sẽ trả lại đường dẫn thư mục dir
bằng dấu gạch chéo, thêm một dấu nếu cần và không khác.
Nếu bạn đã có chuỗi lại đường dẫn một phần trong một danh sách, bạn có thể làm một cái gì đó như:
(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"
hoặc như một sự thay thế, nếu bạn muốn bao gồm tên tập tin trong danh sách, bạn có thể sử dụng directory-file-name
mà không trái ngược với 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"
(? có người hãy sửa lại cho tôi nếu sử dụng directory-file-name
vào một tổ chức phi thư mục không phải là cầm tay)
Điều gì sẽ xảy ra nếu nó có phần bắt đầu bằng '/' ví dụ: '"/p/q/"'? – qazwsx
Nếu đó là lúc bắt đầu, sau đó không có vấn đề (theo ví dụ của tôi ở trên). Nếu nó không phải lúc bắt đầu, thì một đường dẫn tuyệt đối không có doanh nghiệp đang ở giữa một chuỗi các thành phần đường dẫn, do đó sẽ gợi ý một lỗi trong logic tạo ra chuỗi đó. – phils
Đây có phải là vấn đề về tính di động mà bạn đang sử dụng một cách rõ ràng "/" trong ví dụ econd không? –
Something như thế này nên làm việc như là một điểm khởi đầu, mặc dù bạn muốn xác thịt nó ra một chút để làm cho nó nền tảng độc lập, vv
(defun append-path-component (path new-part)
(if (string-match ".*/$" path)
(concat path new-part)
(concat path "/" new-part)))
Theo thường lệ, có lẽ một số chút elisp đã làm điều này mà tôi không biết.
Cảm ơn.Ngoài ra, tôi đang tìm kiếm những chức năng có sẵn và có tính năng có sẵn. – qazwsx
Đây là tính di động không thành công. Bạn không bao giờ phải gõ một con đường riêng biệt trong mã lisp của bạn. –
event_jr: 'directory-sep-char' đã lỗi thời, và đã được gỡ bỏ hoàn toàn trong Emacs 24. Docstring cũ nói" Giá trị luôn luôn là '? /'. Không sử dụng biến này, chỉ cần sử dụng '/'. " – phils
(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/"
Cách dễ nhất để tập hợp tên tệp từ các phần của nội dung có vấn đề là với tên tệp mở rộng. Ví dụ:
(expand-file-name "foo.txt")
hình thức phổ biến này sẽ cung cấp cho bạn một tên tập tin đầy đủ dựa trên mặc định thư mục:
/home/me/foo.txt
nhưng nếu bạn có một biến 'dir' có nội dung là "/ home/họ/subdir "và muốn sử dụng điều đó, hãy thực hiện việc này:
(expand-file-name "foo.txt" dir)
không quan trọng nếu dir kết thúc bằng/hay không. Nếu bạn đang ở trên một số nền tảng khác, và chứa các dấu gạch chéo khác, nó sẽ làm điều đúng sau đó quá. Bạn có pha trộn không? Chỉ cần chồng họ:
(expand-file-name "foo.txt" (expand-file-name "somesubdir" dir))
Trừ khi bạn thực sự quan tâm về việc giữ tên tập tin tương đối như người thân, sau đó nó luôn luôn tốt hơn nhiều để tránh concat
và sử dụng expand-file-name
để thay thế.
Bạn có thể vui lòng đưa ra một ví dụ để minh họa sự khác biệt của cả hai? – qazwsx
Nếu bạn xử lý thao tác với tệp, nối và tách tệp, kiểm tra các thư mục trống và như vậy, tôi khuyên bạn nên cài đặt f.el
, thư viện thao tác tệp hiện đại. Bạn sẽ có một tập hợp lớn các chức năng thao tác tập tin và filepath dưới một không gian tên và sẽ không bao giờ tái tạo lại bánh xe nữa.
Chức năng bạn cần là f-join
, nó nối các phần của đường dẫn, chỉ thêm dấu gạch chéo khi cần.
trên Linux, gấp đôi // biểu tượng trong đường dẫn tệp thường (luôn luôn tôi nghĩ) được hiểu là một /, vì vậy việc thêm một ký tự không phải là vấn đề. – Tyler
Điều này cần phải hoạt động trên tất cả các nền tảng. – qazwsx