elisp - एमएसीएस लिस्प में एक ही पूर्ण पथ में कई पथ घटकों में शामिल होने का सही तरीका क्या है?




filenames path-manipulation (4)

मान लीजिए कि मेरे पास चर और file जिनमें क्रमशः एक निर्देशिका और एक फ़ाइलनाम का प्रतिनिधित्व करने वाले तार हैं। इमैक लिस्प में उचित तरीका क्या है जो उन्हें फाइल में पूर्ण पथ में शामिल कर सकता है?

उदाहरण के लिए, यदि dir "/usr/bin" और file "ls" , तो मुझे "/usr/bin/ls" । लेकिन अगर इसके बजाय dir "/usr/bin/" , तो मैं अभी भी वही चीज चाहता हूं, जिसमें कोई दोहराव नहीं है।


आप इसके लिए expand-file-name उपयोग कर सकते हैं:

(expand-file-name "ls" "/usr/bin")
"/usr/bin/ls"
(expand-file-name "ls" "/usr/bin/")
"/usr/bin/ls"

संपादित करें: यह केवल निरपेक्ष निर्देशिका नामों के साथ काम करता है। मुझे लगता है कि ट्रे का जवाब बेहतर समाधान है।


मैं एक पथ पर कई नेस्टेड निर्देशिकाओं में शामिल होना चाहता था। मूल रूप से मैंने कई expand-file-name कॉल का उपयोग किया, जैसे:

(expand-file-name "b" (expand-file-name "a" "/tmp"))
"/tmp/a/b"

हालांकि यह बल्कि क्रिया है, और पीछे की ओर पढ़ता है।

इसके बजाय मैंने एक फ़ंक्शन लिखा जो पायथन के os.path.join की तरह काम करता है:

(defun joindirs (root &rest dirs)
  "Joins a series of directories together, like Python's os.path.join,
  (dotemacs-joindirs \"/tmp\" \"a\" \"b\" \"c\") => /tmp/a/b/c"

  (if (not dirs)
      root
    (apply 'joindirs
           (expand-file-name (car dirs) root)
           (cdr dirs))))

यह इस तरह काम करता है:

(joindirs "/tmp" "a" "b")
"/tmp/a/b"
(joindirs "~" ".emacs.d" "src")
"/Users/dbr/.emacs.d/src"
(joindirs "~" ".emacs.d" "~tmp")
"/Users/dbr/.emacs.d/~tmp"

यहाँ मेरा उपयोग है:

(defun catdir (root &rest dirs)
  (apply 'concat (mapcar
          (lambda (name) (file-name-as-directory name))
          (push root dirs))))

@ Dbr से अंतर:

  1. एक "emacs निर्देशिका नाम" लौटाता है, यानी एक अनुगामी स्लैश के साथ एक मूल्य
  2. यह root का विस्तार नहीं करता है यदि root सापेक्ष है (नोट देखें)
  3. root को root रूप में मानते हैं, जबकि joindirs root रूप में "/" शुरू होने वाले पहले घटक का उपयोग करेंगे।

टिप्पणियाँ

कई फ़ाइल हैंडलिंग फ़ंक्शंस (सभी, अधिकांश, ???) निरर्थक स्लैश को सामान्य करेंगे और रिश्तेदार पथों पर expand-file-name (या समान) कॉल करेंगे, इसलिए # 2 और # 3 वास्तव में कोई फर्क नहीं पड़ सकता है।


निर्देशिका नामों के लिए मैनुअल के माध्यम से पढ़ना, आपको उत्तर मिलेगा:

एक निर्देशिका नाम को देखते हुए, आप इसे एक रिश्तेदार फ़ाइल नाम के साथ जोड़ सकते हैं।

 (concat dirname relfile)

यह सत्यापित करना सुनिश्चित करें कि ऐसा करने से पहले फ़ाइल नाम सापेक्ष है। यदि आप एक पूर्ण फ़ाइल नाम का उपयोग करते हैं, तो परिणाम वाक्यविन्यास रूप से अमान्य हो सकते हैं या गलत फ़ाइल को संदर्भित कर सकते हैं।

यदि आप इस तरह के संयोजन को बनाने में निर्देशिका फ़ाइल नाम का उपयोग करना चाहते हैं, तो आपको पहले file-name-as-directory का उपयोग करके इसे निर्देशिका नाम में बदलना होगा:

 (concat (file-name-as-directory dirfile) relfile) 

हाथ से स्लैश समेटने की कोशिश न करें, जैसे कि

 ;;; Wrong!
 (concat dirfile "/" relfile) 

क्योंकि यह पोर्टेबल नहीं है। हमेशा file-name-as-directory

अन्य कमांड जो उपयोगी हैं, वे हैं: file-name-directory , file-name-nondirectory , और फाइल नेम कम्पोनेंट्स सेक्शन में अन्य।