शेल कमांड को चुपचाप कैसे निष्पादित करें?


70

:!<command>शेल में एक कमांड निष्पादित करने के लिए इस्तेमाल किया जा सकता है। लेकिन यह मेरे टर्मिनल को "लेता है" और stdoutउस विशेष कमांड के साथ इसे भरता है ।

मैं पृष्ठभूमि में एक कमांड को कैसे निष्पादित करता हूं जो केवल मुझे गैर-शून्य निकास कोड पर सूचित करता है?


1
क्या आप + अजगर इंटरफ़ेस, या अन्य भाषा इंटरफेस में से एक का उपयोग करने के लिए तैयार होंगे?
joeytwield

1
@joeytwiddle हां
ऑरेंजट्यूक्स

जवाबों:


52

:silent exec "!command"

ध्यान दें कि जब आपका कमांड निष्पादित हो रहा हो तब भी आपका vim सेशन कब्जा रहेगा। यह विम के समकालिक प्रकृति के कारण है। आप CTRL + z (बैकग्राउंड पर Vim भेजने के लिए) दबाकर अपने शेल पर वापस आ सकते हैं और फिर कमांड fgको हमेशा की तरह फिर से शुरू कर सकते हैं ।

एसिंक्रोनस रूप से चीजों को करने के लिए, टिम पोप के प्लग - इन विम-प्रेषण या प्रोजेक्ट नियोविम पर एक नज़र डालें , जिसमें एसिंक्रोनस कमांड निष्पादन के लिए मूल समर्थन है, जिसे आप प्लगइन नियोमेक का उपयोग करके आसानी से लाभ उठा सकते हैं। विम के नवीनतम संस्करण में अतुल्यकालिक कार्यों के लिए समर्थन भी है।

देखें : h: चुप


5
यह भी पहली बात है कि मैंने कोशिश की थी जब मैंने प्रश्न देखा :-) लेकिन अगर आप एक कमांड का उपयोग करते हैं जो stdout (या stderr) को आउटपुट करता है, तो यह आपकी मुख्य Vim विंडो (कोशिश :silent !ls) को "क्लोबर" करेगा ... यह भी नहीं करता है 'नॉन-एग्जिट कोड पर उचित आउटपुट न दें ... तो मुझे डर है कि यह सिर्फ इस्तेमाल करने की तुलना में थोड़ा अधिक शामिल है :silent...
मार्टिन टूरनोइज

मुझे माफ करें। अपनी टिप्पणी लिखते समय अतुल्यकालिक निष्पादन के बारे में कुछ नोट्स जोड़े। पता नहीं कैसे बाहर निकलने की स्थिति के मुद्दे को संबोधित करने के लिए। आप Freenode पर #vim में प्रयास करना चाह सकते हैं।
ओलिवरयूव

मैं यह भी ध्यान देना चाहता हूं कि न :silent exec "!ls"ही :silent !lsविम के मेरे संस्करण पर कोई आउटपुट न तो दिखाए और न ही पैच 1-2 के साथ 7.4।
ओलिवरयूव

3
हम्म, यहाँ मुझे बाद में क्या मिला है :silent !ls: i.stack.imgur.com/1XvS6.png ... मुझे ^Lइसे फिर से ठीक करने के लिए प्रेस करने की आवश्यकता है ...
मार्टिन टूरनोइज

विम-प्रेषण निश्चित रूप से दी गई समस्या के समाधान की तरह दिखता है।
joeytwiddle

30

दर्ज संदेश ट्रिगर किए बिना एक कमांड निष्पादित करने के लिए, जैसे:

जारी रखने के लिए ENTER या कमांड टाइप करें

निम्नलिखित सरल उदाहरण का प्रयास करें:

:silent !echo Hello

फिर Vim करने पर स्क्रीन को रिफ्रेश करने के लिए Ctrl+ L(या :redraw!) दबाएं ।

ताज़ा करने की आवश्यकता से बचने के लिए, आप अपने स्वयं के कस्टम कमांड को परिभाषित कर सकते हैं, जैसे:

:command! -nargs=1 Silent execute ':silent !'.<q-args> | execute ':redraw!'

(: बिना टिप्पणी अब, आप एक शेल कमांड को चलाने के लिए नए विम आदेश का उपयोग कर सकते हैं ! और पूंजी के साथ एस ):

:Silent ps

स्रोत: विम हिट साइट पर संकेत देने के लिए "हिट एंटर जारी रखने के लिए" से बचें


1
गैर-शून्य निकास कोड पर आपको कैसे सूचित किया जाता है?
मार्टिन टूरनोइज

1
नॉन-जीरो एग्जिट कोड का समाधान नहीं, लेकिन इसे जोड़ने के लिए, यह साइलेंट कमांड :Silent ctags -R . > /dev/null &पृष्ठभूमि में चलने जैसी कमांड की अनुमति देता है । Stdout को / dev / null पर भेजना आउटपुट को vim बफर में प्रदर्शित होने से रोकता है।
ftvs

10

एक त्वरित और गंदा समाधान (शुद्ध विम्स्क्रिप्ट में)

यह पृष्ठभूमि में एक प्रक्रिया शुरू कर सकता है:

:!slow_command_here > /tmp/output 2>&1 &

लेकिन विम को यह पता लगाने के लिए एक तरीका चाहिए कि प्रक्रिया कब पूरी हुई है, और कैसे, तो चलो एक मार्कर फ़ाइल का उपयोग करें:

:!(rm -f /tmp/finished; slow_command_here > /tmp/output 2>&1; echo "$?" > /tmp/finished) &

अब हम विम को हर बार जांचने के लिए कह सकते हैं कि क्या प्रक्रिया पूरी हो चुकी है:

:augroup WaitForCompletion
:autocmd!
:autocmd CursorHold * if filereadable('/tmp/finished') | exec "augroup WaitForCompletion" | exec "au!" | exec "augroup END" | echo "Process completed with exit code ".readfile('/tmp/finished')[0] | end
:augroup END

अरे यह सुंदर नहीं है, लेकिन यह काम करता है!

नुकसान

जब तक आप कर्सर नहीं ले जाते, दुर्भाग्य से ऊपर का ऑटोकैम ट्रिगर नहीं होगा। और यदि आप एक समय में एक से अधिक पृष्ठभूमि प्रक्रिया को चलाना चाहते थे, तो आपको उन फ़ाइलों में और ऑटोकैड समूह के नाम के लिए अद्वितीय आईडी जोड़ना होगा।

इसलिए यदि आप एक अतिरिक्त निर्भरता को संभाल सकते हैं, तो आप दूसरे उत्तर में उल्लिखित विम-प्रेषण प्लगइन की तरह आज़माए गए और परीक्षण किए गए समाधान का उपयोग करके बेहतर हो सकते हैं।

आउटपुट प्रदर्शित करना

यदि आप केवल बाहर निकलने के कोड के बजाय प्रक्रिया के आउटपुट को देखना चाहते हैं , तो अंतिम को इसके साथ बदलें :echo

silent botright pedit /tmp/output

यह पूर्वावलोकन विंडो खोल देगा। इसके बजाय क्विकफ़िक्स त्रुटि सूची का उपयोग करने के लिए:

silent cget /tmp/output | copen

क्विकफ़िक्स सूची आपको उपयोग करने में आसानी से त्रुटियों को नेविगेट करने देती है :cnext। हालाँकि copen, यह खुलने पर आपके कर्सर को क्विकफिक्स विंडो में ले जाता है, जो संभवतः आश्चर्यजनक / कष्टप्रद होगा।

(कि का संभावित हल के साथ QF विंडो खोलने के लिए होगा :copenजब शुरू में प्रक्रिया शुरू करने से है, तो आप करेंगे नहीं अंत में इसे कहते हैं की जरूरत है।)


2
यहाँ केवल यही एक उत्तर है जो वास्तव में इस प्रश्न का उत्तर देता है: "पृष्ठभूमि में एक कमांड निष्पादित करें जो केवल मुझे एक गैर-शून्य निकास कोड पर सूचित करता है" ... मुझे नहीं पता कि अन्य उत्तर भी बिल्कुल क्यों नहीं हैं ...
मार्टिन टूरनोइज

2
मेरा मानना ​​है कि उनके पास उत्थान है क्योंकि वे पूरी तरह से सवाल के शीर्षक का जवाब देते हैं , जो आगंतुकों को इस पृष्ठ पर लाता है। "शैल कमांड को चुपचाप कैसे निष्पादित किया जाए?" एक आम एसई घटना! आगंतुक आभारी हैं, लेकिन शायद अनुशासित नहीं हैं।
joeytwiddle

एक आदर्श दुनिया में, हमारे पास शायद दो अलग-अलग प्रश्न होंगे: "शेल कमांड को चुपचाप कैसे निष्पादित करें?" और "पृष्ठभूमि में शेल कमांड कैसे निष्पादित करें?" ताकि गोगलर्स पा सकें कि वे क्या ढूंढ रहे हैं।
joeytwiddle

6

पृष्ठभूमि में एक कमांड चल रहा है

मैं एक कमांड चला रहा था जो थोड़े से ब्लॉक हो गया था, और मैं वास्तव में आउटपुट के बारे में परवाह नहीं करता था। टर्मिनल / एमुलेटर से जुड़ी प्रक्रिया को शुरू करने के बजाय सिस्टम को शुरू करने और सभी आउटपुट को / dev / null में रीडायरेक्ट करके इसका ध्यान रखा जा सकता है। उदाहरण के लिए:

:silent exec "!(espeak 'speaking in background'&) > /dev/null"

(...&)पृष्ठभूमि में चलाता है और > /dev/nullकरने के लिए सभी उत्पादन पुनर्निर्देश /dev/null(कुछ नहीं)।

कोष्ठक आउटपुट को एक उप-धारा (या ऐसा कुछ) में फंसाता है, लेकिन इसका वर्तमान शेल से जुड़ा नहीं होने (बड़ा सौदा नहीं) का दुष्प्रभाव है।

मैपिंग के साथ पृष्ठभूमि में चुपचाप एक कमांड चलाना

मुझे बस एहसास हुआ कि यदि आप वास्तव में हैं , तो इसे मैप करते हुए, आप कुछ ऐसा कर सकते हैं

nnoremap <silent> <leader>e :!$(espeak 'speaking in the background'&) > /dev/null

उपरोक्त कमांड बार में कुछ भी प्रदर्शित नहीं करेगा और इसके अलावा, विम के बाहर टर्मिनल में कुछ भी प्रदर्शित नहीं करेगा। इसे मैप किया जाएगा <leader> e, जो \ eडिफ़ॉल्ट रूप से है।

एक कमांड चलाना, इसके आउटपुट को कैप्चर करना, इसकी सामग्री प्रदर्शित करना

(एक और संपादन - और शायद सबसे साफ वाला)। यदि आप चुनते हैं तो यह एक कमांड का आउटपुट प्रदर्शित करेगा :


एक नया टैब सम्मिलित करें:

silent exec "!(echo 'hello. I'm a process! :)') > /tmp/vim_process" | :tabedit /tmp/vim_process

एक रासायनिक स्प्लिट सम्मिलित करें:

silent exec "!(echo 'hello. I'm a process :)') > /tmp/vim_process" | :vs /tmp/vim_process

एक हॉरिज़ॉन्टल स्प्लिट में शामिल हों:

silent exec "!(echo 'hello. I'm a process :)') > /tmp/vim_process" | :sp /tmp/vim_process

... आप जो चाहे करें


5

यदि आपको निकास कोड की परवाह नहीं है, तो आप इसके साथ जा सकते हैं:

:call system('/usr/bin/zathura using-docker.pdf &')

1
यदि आप बाहर निकलने के कोड के बारे में परवाह करते हैं, तो v:shell_errorचर आपको बताएगा
जेरोम डलबर्ट

4

सुनिश्चित नहीं है कि यह आपकी आवश्यकताओं के अनुरूप है, (पृष्ठभूमि प्रक्रियाओं को संभालता नहीं है foo & - जैसे कि "पृष्ठभूमि में" से आपका मतलब है, तो निश्चित नहीं है ), लेकिन एक कस्टम कमांड का उपयोग इस प्रकार किया जा सकता है:

fun! s:PraeceptumTacet(cmd)
    silent let f = systemlist(a:cmd)
    if v:shell_error
        echohl Error
        echom "ERROR #" . v:shell_error
        echohl WarningMsg
        for e in f
            echom e
        endfor
        echohl None
    endif
endfun

command! -nargs=+ PT call s:PraeceptumTacet(<q-args>)

फिर उदाहरण के लिए उपयोग करें:

:PT ls -l
:PT foobar
ERROR #127
/bin/bash: foobar: command not found

यदि आपको जरूरत नहीं है / त्रुटि संदेश एक सरल system()पर्याप्त हो सकता है, तो v:shell_errorउदाहरण के लिए जाँच करें और रिपोर्ट करें echo Error!

से मदद v: shell_error :

                                        v:shell_error shell_error-variable
v:shell_error   Result of the last shell command.  When non-zero, the last
                shell command had an error.  When zero, there was no problem.
                This only works when the shell returns the error code to Vim.
                The value -1 is often used when the command could not be
                executed.  Read-only.
                Example: >
    :!mv foo bar
    :if v:shell_error
    :  echo 'could not rename "foo" to "bar"!'
    :endif
                "shell_error" also works, for backwards compatibility.

यह वास्तव में इसे पृष्ठभूमि में नहीं चला रहा है; इसके खत्म होने के लिए आपको अभी भी इंतजार करने की जरूरत है।
मार्टिन टूरनोइज

@Carpetsmoker: हाँ, इस प्रकार मेरी टिप्पणी "... में पृष्ठभूमि प्रक्रियाओं को नहीं संभालती है foo &" । क्यू पाठ से एक पूरे के रूप में मैं इसे या तो होने के रूप में व्याख्या की। या तो "बाहरी आदेश उर्फ पृष्ठभूमि के रूप में निष्पादित करें" या "पृष्ठभूमि प्रक्रिया के रूप में बाहरी आदेश _and_ रूप में निष्पादित करें।" । मैंने मुख्य रूप से क्यू आदि के शीर्षक के आधार पर उत्तर दिया - और "निश्चित नहीं ..." पर एक टिप्पणी जोड़ी - और इसे या तो स्पष्ट करने के लिए ओपी पर छोड़ दिया।
20

3

विम 8 ने नौकरियों का समर्थन किया। कोई भी प्लगइन्स पर भरोसा किए बिना पृष्ठभूमि में बाहरी कमांड चला सकता है। उदाहरण के लिए, वर्तमान स्थान पर मार्कडाउन सर्वर ( मार्सवर्टर ) चलाने के लिए और विम सत्र को ब्लॉक करने के लिए नहीं:

:call job_start('markserv .')

यह वर्तमान vim प्रक्रिया की उप-प्रक्रिया के रूप में मार्सरव प्रक्रिया शुरू करता है। आप इससे सत्यापित कर सकते हैं pstree

देखें job_start


2

मैं निम्नलिखित कोड का उपयोग करता हूं:

command! -nargs=1 Silent call SilentExec(<q-args>)

function! SilentExec(cmd)
  let cmd = substitute(a:cmd, '^!', '', '')
  let cmd = substitute(cmd, '%', shellescape(expand('%')), '')
  call system(cmd)
endfunction

अब आप निम्न टाइप कर सकते हैं

:Silent !your_command

यह लगभग विम की अंतर्निहित silent !कमांड जैसा दिखता है , केवल राजधानी को छोड़कर S। यह एक वैकल्पिक के लिए भी अनुमति देता !है ताकि यह और भी समान दिख सके। system()शेल कमांड को कॉल वास्तव में चुप कर देता है: कोई स्क्रीन नहीं चमकती है और कोई रीड्रा नहीं।

(और यदि आपको कभी भी स्थिति कोड की आवश्यकता हो, तो आप v:shell_errorचर की जांच कर सकते हैं, अधिक जानकारी के लिए सहायता देखें)


1

AsyncRun प्लगइन अगर यह के लिए बनाया गया है, यह आप Vim8 / NeoVim में पृष्ठभूमि में खोल आदेशों को चलाने और QuickFix विंडो में उत्पादन प्रदर्शित करने के लिए अनुमति देता है।

!आदेश के प्रतिस्थापन के रूप में :

:AsyncRun ls -la /

आप क्विकफिक्स विंडो में आउटपुट को पूरी तरह से छिपा सकते हैं:

:AsyncRun -mode=3 ls -la /

जब नौकरी समाप्त हो जाती है, तो AsyncRun आपको एक विकल्प पारित करके सूचित करेगा -post:

:AsyncRun -post=some_vim_script   ls -la /

-postनौकरी से समाप्त होने के बाद परिभाषित विम स्क्रिप्ट को निष्पादित किया जाएगा।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.