फ़ाइल नाम पैटर्न या निर्देशिका के लिए बैश समापन


13

मैं एक बैश पूरा स्क्रिप्ट पाने के लिए और कुछ परेशानी होने की कोशिश कर रहा हूँ।

मैं इसे स्थापित करना चाहूंगा ताकि सूचीबद्ध पूर्णियां या तो किसी विशेष एक्सटेंशन, या निर्देशिकाओं से मेल खाने वाली फाइलें हों (जिनमें उस एक्सटेंशन की फाइलें शामिल हो सकती हैं या नहीं भी)।

मुझे जो परेशानी हो रही है, वह यह है कि मैं फ़ाइलों और निर्देशिकाओं को पूरा करने का एकमात्र तरीका प्राप्त कर सकता हूं -o plusdirs -f -X '!*.txt', जैसे कि कुछ का उपयोग करके , लेकिन जब मैं किसी एक निर्देशिका को पूरा करने देता हूं, तो यह अंत में एक जगह जोड़ता है, बजाय स्लेश।

_xyz()
{
  local cur=${COMP_WORDS[COMP_CWORD]}
  local prev=${COMP_WORDS[COMP_CWORD-1]}

  #COMPREPLY=( $( compgen -f -X '!*.txt' -- $cur ) )
  #COMPREPLY=( $( compgen -f -G '*.txt' -- $cur ) )
  #COMPREPLY=( $( compgen -o filenames -f -X '!*.txt' -- $cur ) )
  #COMPREPLY=( $( compgen -o dirnames  -f -X '!*.txt' -- $cur ) )
  COMPREPLY=( $( compgen -o plusdirs  -f -X '!*.txt' -- $cur ) )
  return 0
}

complete -F _xyz xyz

मैंने सभी टिप्पणी की गई लाइनों को भी आज़माया है, लेकिन वे निर्देशिकाओं का विस्तार भी नहीं करते हैं।

परीक्षण के लिए, मैं इसे एक .txt फ़ाइल और एक निर्देशिका "dir" (इसके अंदर एक .txt फ़ाइल के साथ, हालांकि यह अभी तक कोई फर्क नहीं पड़ता) के साथ एक निर्देशिका में चला रहा है। टंकण xyz <TAB>इस समारोह सूचियों निर्देशिका और .txt फ़ाइल है, लेकिन लेखन के साथ xyz d<TAB>फैलता करने के लिए xyz dir(अच्छी तरह से, एक अंतरिक्ष के साथ "dir" के बाद)।

जवाबों:


10

आप समारोह को देखें, तो _cd()में / etc / bash_completion , आप देखेंगे कि यह अनुगामी ही स्लेश संलग्न कर देता है और कहा कि देखेंगे पूरा विकल्प के साथ हो जाता है कहा जाता है -o nospaceके लिए सीडी

आप xyz के लिए भी ऐसा कर सकते हैं , लेकिन अलग-अलग सत्यापित करने के लिए कि यदि पाया गया एक निर्देशिका है (यदि हां, तो स्लैश को जोड़ें) या फ़ाइल (यदि ऐसा है, तो अंतरिक्ष को जोड़ें)। यह सभी पाए गए मैचों को संसाधित करने के लिए एक लूप में किया जाना चाहिए।

इसके अलावा, रिक्त स्थान को सही ढंग से संभालने के लिए, आपको आंतरिक फ़ाइल विभाजक को केवल newline पर सेट करना होगा और रिक्त स्थान से बचना होगा। के IFS=$'\n'साथ संयोजन में उपयोग करना printf %qलगभग सभी पात्रों के साथ पूरा होने का काम करता है। 1 अनुगामी अंतरिक्ष से बचने के लिए विशेष ध्यान रखा जाना चाहिए।

निम्नलिखित काम करना चाहिए:

_xyz ()
{
    local IFS=$'\n'
    local LASTCHAR=' '

    COMPREPLY=($(compgen -o plusdirs -f -X '!*.txt' \
        -- "${COMP_WORDS[COMP_CWORD]}"))

    if [ ${#COMPREPLY[@]} = 1 ]; then
        [ -d "$COMPREPLY" ] && LASTCHAR=/
        COMPREPLY=$(printf %q%s "$COMPREPLY" "$LASTCHAR")
    else
        for ((i=0; i < ${#COMPREPLY[@]}; i++)); do
            [ -d "${COMPREPLY[$i]}" ] && COMPREPLY[$i]=${COMPREPLY[$i]}/
        done
    fi

    return 0
}

complete -o nospace -F _xyz xyz

1 न्यूलाइन वर्ण यहां स्पष्ट अपवाद है, क्योंकि यह एक आंतरिक फ़ाइल विभाजक है।


यह बहुत अच्छा काम करता है (हालाँकि यह बहुत बुरा है क्योंकि इसमें निर्मित नहीं है)। धन्यवाद!
रोब I

1
"$ {COMP_WORDS [COMP_CWORD]}" के बजाय "$ 2" का उपयोग न करने का कोई कारण?
एडवर्ड फॉक

3

मुझे लगता है कि यह सरल समाधान उस में काम करता है:

  1. निर्देशिका और फ़ाइलों से मेल खाता है जो अंत में हैं .txt
  2. फ़ाइल नामों में रिक्त स्थान संभालता है
  3. फ़ोल्डर के अंत में कोई अनुगामी स्थान के साथ स्लैश जोड़ता है
  4. एक फ़ाइल पूरा होने के मैच के अंत में स्थान जोड़ता है

चाबी -o filenamesपूरी होने के लिए गुजर रही थी । यह आरएचईएल 5.3 पर जीएनयू बैश 3.2.25 और ओएसएक्स पर जीएनयू बैश 4.3.18 का परीक्षण किया गया था

_xyz()
{
  local cur=${COMP_WORDS[COMP_CWORD]}

  local IFS=$'\n'
  COMPREPLY=( $( compgen -o plusdirs  -f -X '!*.txt' -- $cur ) )
}

complete -o filenames -F _xyz xyz

हाँ, यह बहुत अच्छा काम लगता है। बहुत सरल, महत्वपूर्ण तर्क को पकड़ने के लिए धन्यवाद!
रोब I
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.