कुछ निर्देशिका के लिए बैश में पूर्ण टैब अक्षम करें जिसमें बड़ी संख्या में फाइलें हैं?


19

मैं बड़ी संख्या में फाइलों के साथ काम कर रहा हूं, जिन्हें मैं एक निर्देशिका में रखता हूं। हर बार जब मैं उस निर्देशिका में जाता हूं और गलती से Tabदो बार दबाता हूं, तो पैटर्न से मेल खाने वाली फ़ाइलों को दिखाने के लिए बहुत लंबा (एक मिनट से अधिक का समय हो सकता है) और मैं इस व्यवहार से काफी नाराज हूं।

उदाहरण के लिए, मेरी निर्देशिका संरचना है:

my-project/
├── docs/
├── data/        <---- contains around 200k files.
└── analyser/

चूंकि मुझे अभी भी पूरा होने से प्यार है, क्या इस सुविधा को केवल data/निर्देशिका में अक्षम करना है ? 5 सेकंड के लिए सेट टाइमआउट की तरह, या एक स्क्रिप्ट जो विशिष्ट निर्देशिका के अंदर स्वचालित रूप से पूर्ण स्विच ऑफ करती है?


क्या आप इस पर zsh स्विच करेंगे? (मुझे नहीं पता कि क्या यह मारपीट में संभव है। मुझे पता है कि यह zsh में संभव है, लेकिन यह आसान नहीं हो सकता है, मैंने जाँच नहीं की है।)
गाइल्स का SO- बुराई होना बंद हो '

जवाबों:


9

यह बिल्कुल सही नहीं है, लेकिन फिर बैश पूरा होना काफी मुश्किल काम है ...

सबसे सरल तरीका प्रति आदेश के आधार पर है, यह थोड़ा अधिक लचीला है FIGNORE, आप कर सकते हैं:

 complete -f -X "/myproject/data/*" vi

यह स्वत: पूर्ण को निर्देश देता है कि viफाइलों के लिए पूरा हो रहा है, और -Xफिल्टर से मेल खाने वाले पैटर्न को हटाने के लिए । नकारात्मक पक्ष यह है कि पैटर्न सामान्यीकृत नहीं है, इसलिए ../dataऔर विविधताएं मेल नहीं खाएंगी।

अगली सबसे अच्छी बात एक कस्टम PROMPT_COMMANDफ़ंक्शन हो सकती है :

# associative arrays of non-autocomplete directories
declare -A noacdirs=([/myproject/data]=1 )

function _myprompt {
    [[ -n "${noacdirs[$PWD]}" ]] && {
       echo autocomplete off
       bind 'set disable-completion on'
    } || {
       echo autocomplete on
       bind 'set disable-completion off'
    }
} 

PROMPT_COMMAND=_myprompt

इस प्रकार से अक्षम पूरा होने (पूरी तरह से) जब आप निर्देशिका में कर रहे हैं, लेकिन यह हर पथ के लिए यह अक्षम कर देता है नहीं सिर्फ इतना है कि निर्देशिका में फाइल।

यह परिभाषित पथों के लिए इसे चुनिंदा रूप से अक्षम करने के लिए आम तौर पर अधिक उपयोगी होगा, लेकिन मेरा मानना ​​है कि एकमात्र तरीका डिफ़ॉल्ट समापन फ़ंक्शन (बैश-4.1 और बाद में complete -D) का उपयोग करना है और इसके बारे में बहुत कुछ गड़बड़ है।

यह आपके लिए काम करना चाहिए , लेकिन इसके अनपेक्षित दुष्प्रभाव हो सकते हैं (अर्थात कुछ मामलों में अपेक्षित पूर्णता में परिवर्तन):

declare -A noacdirs=([/myproject/data]=1 )

_xcomplete() {
    local cur=${COMP_WORDS[COMP_CWORD]} # the current token

    name=$(readlink -f "${cur:-./}")  # poor man's path canonify
    dirname=$(dirname "$name/.")

    [[ -n "${noacdirs[$dirname]}" ]] && {
        COMPREPLY=( "" )   # dummy to prevent completion
        return
    }
    # let default kick in
    COMPREPLY=()
}

complete -o bashdefault -o default -F _xcomplete vi

यह पूरा होने के लिए काम करता है vi, अन्य कमांड को आवश्यकतानुसार जोड़ा जा सकता है। यह पथ या कार्यशील निर्देशिका की परवाह किए बिना नामित निर्देशिकाओं में फ़ाइलों के लिए पूरा करना बंद कर देना चाहिए।

मेरा मानना ​​है कि सामान्य दृष्टिकोण के साथ complete -Dगतिशील रूप से प्रत्येक कमांड के लिए पूरा होने वाले कार्यों को जोड़ना है क्योंकि यह सामना करना पड़ा है। किसी को complete -Eइनपुट बफ़र खाली होने पर कमांड नाम पूरा करने की भी आवश्यकता हो सकती है ।


अपडेट यहां PROMPT_COMMANDऔर फंक्शन सॉल्यूशंस का हाइब्रिड वर्जन है , मुझे लगता है कि इसे समझना और हैक करना थोड़ा आसान है:

declare -A noacdirs=([/myproject/data]=1 [/project2/bigdata]=1)

_xcomplete() {
    local cmd=${COMP_WORDS[0]}
    local cur=${COMP_WORDS[COMP_CWORD]} # the current token

    [[ -z "$cur" && -n "$nocomplete" ]] && {
        printf "\n(restricted completion for $cmd in $nocomplete)\n"  
        printf "$PS2 $COMP_LINE"
        COMPREPLY=( "" )   # dummy to prevent completion
        return
    }
    COMPREPLY=()       # let default kick in
}

function _myprompt {
    nocomplete=
    # uncomment next line for hard-coded list of directories
    [[ -n "${noacdirs[$PWD]}" ]] && nocomplete=$PWD
    # uncomment next line for per-directory ".noautocomplete"
    # [[ -f ./.noautocomplete ]] && nocomplete=$PWD
    # uncomment next line for size-based guessing of large directories
    # [[ $(stat -c %s .) -gt 512*1024 ]] && nocomplete=$PWD
} 

PROMPT_COMMAND=_myprompt
complete -o bashdefault -o default -F _xcomplete vi cp scp diff

nocompleteजब आप कॉन्फ़िगर की गई निर्देशिकाओं में से एक दर्ज करते हैं तो यह प्रॉम्प्ट फ़ंक्शन चर सेट करता है । संशोधित पूरा होने वाला व्यवहार केवल तभी होता है जब वह चर गैर-रिक्त होता है और केवल जब आप खाली स्ट्रिंग से पूरा करने का प्रयास करते हैं, तो इस प्रकार आंशिक नामों को पूरा करने की अनुमति देता है ( -z "$cur"पूरी तरह से रोकने के लिए स्थिति को हटा दें )। printfमूक ऑपरेशन के लिए दो पंक्तियों पर टिप्पणी करें ।

अन्य विकल्पों में एक प्रति-निर्देशिका .noautocompleteफ़्लैग फ़ाइल शामिल होती है जिसे आप touchआवश्यकतानुसार डायरेक्ट्री में कर सकते हैं ; और GNU का उपयोग करके निर्देशिका आकार का अनुमान लगाना stat। आप उन तीन विकल्पों में से किसी एक या सभी का उपयोग कर सकते हैं।

( statविधि केवल एक अनुमान है , रिपोर्ट की गई निर्देशिका का आकार इसकी सामग्री के साथ बढ़ता है, यह एक "उच्च पानी का निशान" है जो आमतौर पर तब नहीं सिकुड़ता है जब कुछ प्रशासनिक हस्तक्षेप के बिना फाइलें हटा दी जाती हैं। यह संभावित रूप से बड़े की वास्तविक सामग्री का निर्धारण करने की तुलना में सस्ता है। निर्देशिका। सटीक फ़ाइल के प्रति व्यवहार और वेतन वृद्धि अंतर्निहित फाइल सिस्टम पर निर्भर करती है। मुझे लगता है कि यह linux ext2 / 3/4 सिस्टम पर कम से कम एक विश्वसनीय संकेतक है।)

एक खाली पूरा होने पर भी बैश एक अतिरिक्त स्थान जोड़ता है (यह केवल एक पंक्ति के अंत में पूरा होने पर होता है)। इसे रोकने के -o nospaceलिए आप completeकमांड को जोड़ सकते हैं ।

एक शेष निगेल यह है कि यदि आप कर्सर को टोकन और हिट टैब की शुरुआत में वापस करते हैं, तो डिफ़ॉल्ट पूर्णता फिर से किक होगी। इसे एक विशेषता पर विचार करें ;-)

(या ${COMP_LINE:$COMP_POINT-1:1}यदि आप ओवर-इंजीनियरिंग को पसंद करते हैं, तो आप चारों ओर फ्यूज़ कर सकते हैं , लेकिन मुझे लगता है कि जब आप बैक अप लेते हैं और कमांड के बीच में पूरा होने का प्रयास करते हैं, तो मैं स्वयं को पूर्ण रूप से चर सेट करने में विफल रहता है।)


6

अपने तो dataनिर्देशिका एक विशिष्ट प्रत्यय, फ़ाइलें हैं जैसे .out , तो आप अपने सेट कर सकते हैं bashचर FIGNOREकरने के लिए ".out"और इन नजरअंदाज कर दिया जाएगा। हालाँकि, निर्देशिका नामों का भी उपयोग करना संभव है, यह वर्तमान कार्यशील निर्देशिका नामों पर मदद नहीं करता है।

उदाहरण:

1 HDDs के साथ भौतिक होस्ट पर हजारों 100KB परीक्षण फ़ाइलें बनाएँ:

for i in {1..200000}; do dd if=/dev/urandom bs=102400 count=1 of=file$i.json; done

bashचर सेट करें :
$ FIGNORE=".json"

परीक्षण फ़ाइल बनाएँ:
$ touch test.out

5,000 फाइलों पर परीक्षण :

$ ls *.json|wc -l
5587
$ vi test.out

Vi और एकल के बीच कोई देरी tabपहले test.outप्रकट नहीं होती है।

50,000 फाइलों पर परीक्षण :

$ ls *.json|wc -l
51854
$ vi test.out

एकल टैब test.outप्रकट होने से पहले दूसरी देरी का एक अंश बनाता है ।

200,000 फाइलों पर परीक्षण :

$ ls *.json|wc -l
bash: /bin/ls: Argument list too long
$ ls | awk 'BEGIN {count=0} /.*.json/ {count++} END {print count}'
200000
$ vi test.out

Vi के बीच 1 सेकंड की देरी और एकल tabसे पहले test.outदिखाई देता है।

संदर्भ:

मैन बैश से एक्साइटमेंट

FIGNORE
              A  colon-separated  list  of  suffixes to ignore when performing filename completion (see READLINE below).  A filename whose suffix matches one of the entries in FIGNORE is
              excluded from the list of matched filenames.  A sample value is ".o:~".

1
मदद नहीं करेगा, ~ 100k फ़ाइलों के बारे में wir w / बनाने की कोशिश करें। फिर मैं करता हूं $ vi <tab><tab>, वैसे भी बहुत समय है। : \
निज़ोद

अभी भी समस्या का समाधान नहीं हुआ, मान लीजिए कि मेरे पास 100k .jsonफाइलें हैं, और एक एकल पाठ फ़ाइल है जिसका नाम है foo.txt। चालू करते FIGNORE='.json'हुए, मुझे टाइप करना है $ vi <tab>और अभी भी आधा मिनट इंतजार करने की आवश्यकता है ताकि यह मुझे पूरा करे $ vi foo.txt। --- वास्तविक परिदृश्य मैं संपादित नहीं करने जा रहा हूँ, या उस प्रकार के अंदर फ़ाइल प्रकारों को मिलाया नहीं जा सकता, लेकिन अगर मैं चालू करता हूं FIGNOREऔर (गलती से) प्रेस टैब पर, मेरा कीबोर्ड लंबे समय तक बिना किसी चीज के संकेत के फ्रीज हो जाएगा Display all 188275 possibilities? (y or n), जो मुझे बताता है कि मैं अपना कीबोर्ड वापस ले सकूं।
निज़ोद

@neizod - क्षमा करें, मैंने बिना किसी लाभ के, डायरेक्टरी स्तर पर काम करने के लिए FIGNORE प्राप्त करने के लिए कई परिदृश्यों की कोशिश की। मुझे लगता है कि एक कस्टम समाधान की आवश्यकता है, या आप बस उस होस्ट पर बैश पूरा होने को अक्षम करते हैं, या हमारी बहन साइट पर उल्लिखित जेडएच समाधान का प्रयास करें।
गेदुवेतिया

क्षमा करें, यह आपके सिस्टम पर केवल 1 सेकंड है, यह मेरे सिस्टम पर लगभग आधा मिनट है। इसलिए मुझे लगता है कि मैं इस समाधान को काम करने के लिए एक नया पीसी खरीदूंगा।
निज़ोद

0

लगता है कि आप क्या चाहते हैं (@ mr.spuratic से कुछ कोड उधार लिया है)

ध्यान दें कि यह आपको पूर्ण पथ (जैसे) का उपयोग करके TAB को दबाने से नहीं रोकता है vim /directory/contains/lots/files<tab><tab>

function cd() {
  builtin cd "$@"
  local NOCOMPLETION=( "/" "/lib" )
  local IS_NOCOMPLETION=0
  for dir in "${NOCOMPLETION[@]}"
  do
    echo $dir
    if [[ $(pwd) == "$dir" ]]
    then
      echo "disable completion"
      bind "set disable-completion on"
      IS_NOCOMPLETION=1
      return
    fi                                                                                                                                                                                              
  done
  if [[ $IS_NOCOMPLETION -eq 0 ]]
  then
    echo "enable completion"
    bind "set disable-completion off"
  fi
}  

pushd/ के बारे में मत भूलना popd। चूंकि यह केवल एक नियमित सरणी का उपयोग करता है, न कि एक सहयोगी सरणी जो यह बैश 3.x में भी काम करेगा।
mr.spuratic
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.