सवाल खोजने के माध्यम से vi आमंत्रित xargs मेरे टर्मिनल तोड़ता है। क्यूं कर?


जब आक्रमण करते हैं vim के माध्यम से find | xargs, इस तरह:

find . -name "*.txt" | xargs vim

आपको इसके बारे में एक चेतावनी मिलती है

Input is not from a terminal

और बाद में बहुत अधिक टूटे व्यवहार के साथ एक टर्मिनल। ऐसा क्यों है?


123
2017-09-15 16:26


मूल


साइड नोट: आप इस ऑपरेशन को पूरी तरह से विम के भीतर कर सकते हैं, इसका उपयोग नहीं कर सकते हैं find या xargs बिल्कुल भी। बिना तर्क के ओपन विम, फिर चलाएं :args **/*.txt<CR>संपादक के अंदर से विम के तर्क सेट करने के लिए। - Trevor Powell
@TrevorPowell: इन सभी वर्षों में, vim मुझे आश्चर्यचकित कभी नहीं बंद कर दिया। - DevSolar
सम्बंधित: grep -l .. | xargs vim एक चेतावनी उत्पन्न करता है, क्यों? यूनिक्स एसई पर - kenorb
सम्बंधित: टर्मिनल xims के साथ विम का आह्वान करने के बाद borked विम एसई में - kenorb
गिटहब बग रिपोर्ट: vim STDIN सेट को / dev / null पर संभाल नहीं करता है। - kenorb


जवाब:


जब आप एक कार्यक्रम के माध्यम से आह्वान करते हैं xargs, कार्यक्रम के stdin (मानक इनपुट) अंक /dev/null। (चूंकि xargs को नहीं पता है मूल stdin, यह अगली सबसे अच्छी बात करता है।)

$ सच | xargs Filan -s
    0 chrdev / dev / null
    1 tty / dev / pts / 1
    2 tty / dev / pts / 1

$ सच | xargs ls -l / dev / fd /

विम उम्मीद करता है कि इसका स्टडीन इसके नियंत्रण टर्मिनल जैसा ही होगा, और विभिन्न टर्मिनल से संबंधित प्रदर्शन करता है ioctlसीधे stdin पर है। जब किया जाता है /dev/null (या कोई गैर-टीटीआई फ़ाइल डिस्क्रिप्टर), वे ioctls व्यर्थ हैं और एनओटीटीई लौटते हैं, जिन्हें चुपचाप अनदेखा किया जाता है।

  • मेरा अनुमान अधिक विशिष्ट कारण पर: स्टार्टअप पर विम पुराने टर्मिनल सेटिंग्स को पढ़ता है और याद करता है, और बाहर निकलने पर उन्हें वापस बहाल करता है। हमारी स्थिति में, जब "पुरानी सेटिंग्स" को गैर-टीटीआई एफडी (फ़ाइल डिस्क्रिप्टर) के लिए अनुरोध किया जाता है, तो विम सभी मान खाली प्राप्त करता है और सभी विकल्प अक्षम होते हैं, और लापरवाही से आपके टर्मिनल पर इसे सेट करते हैं।

    आप इसे चलाकर देख सकते हैं vim < /dev/null, इसे छोड़कर, फिर चल रहा है stty, जो पूरी तरह से उत्पादन करेगा <undef>रों। लिनक्स पर, चल रहा है stty sane टर्मिनल को फिर से उपयोग करने योग्य बना देगा (हालांकि यह मर्जी इस तरह के विकल्प खो दिया है iutf8, संभवतः बाद में मामूली परेशानी पैदा कर रहा है)।

आप इसे विम में एक बग पर विचार कर सकते हैं, क्योंकि यह कर सकते हैं खुला /dev/tty टर्मिनल नियंत्रण के लिए, लेकिन नहीं। (स्टार्टअप के दौरान किसी बिंदु पर, विम अपने stderr को stdin पर डुप्लिकेट करता है, जो इसे आपके इनपुट कमांड को पढ़ने की अनुमति देता है - लिखने के लिए खोले गए एफडी से - लेकिन यह भी पर्याप्त जल्दी नहीं किया जाता है।)


85
2017-09-15 16:41



... एक flourish के साथ। आपका बहुत बहुत धन्यवाद! - DevSolar
+1, और टीएल के लिए; डीआर लोग बस दौड़ते हैं stty sane - rahmanisback
@rahmanisback: अन्य उत्तरों, प्लस ट्रेवर की टिप्पणी, सभी जगहों पर टर्मिनल ब्रेकेज से बचने के तरीके उपलब्ध कराए गए हैं। मैंने भ्रष्टाचार का जवाब स्वीकार कर लिया, क्योंकि मेरा सवाल "क्यों" था, न कि "कैसे बचें" - जो कि कवर किया गया है एक और सवाल वास्तव में पैदा की यह वाला। - DevSolar
@ डेवोलर समझा, लेकिन मेरे जैसे निराश लोगों के बारे में सोचें, जो कि उस व्यवहार से छुटकारा पाने के लिए कैसे हैं- दुर्भाग्य से - "क्यों" का अध्ययन करने के लिए अभी पर्याप्त समय है, जो कि फिर भी बहुत दिलचस्प है। - rahmanisback
जब मेरा टर्मिनल टूट जाता है, इस तरह, मैं उपयोग करता हूं reset के बजाय stty sane और उसके बाद यह ठीक काम करता है। - Capi Etheriel


भ्रष्टाचार के जवाब से निम्नलिखित के बाद, xargs अंक stdin सेवा मेरे /dev/null


ओएसएक्स / बीएसडी से man xargs

-ओ बच्चे की प्रक्रिया में stdin / dev / tty के रूप में फिर से खोलें
        आदेश निष्पादित करने से पहले। यह उपयोगी है
        यदि आप xargs को एक इंटरैक्टिव एप्लिकेशन चलाने के लिए चाहते हैं।

इस प्रकार कोड की निम्नलिखित पंक्ति आपके लिए काम करनी चाहिए:

ढूंढो -नाम "* .txt" | xargs -o vim

जीएनयू के लिए man xargs कोई झंडा नहीं है, लेकिन हम समस्या को हल करने के लिए स्पष्ट रूप से / dev / tty में पास कर सकते हैं:

ढूंढो -नाम "* .txt" | xargs bash -c '</ dev / tty vim "$ @"' ignoreme

अनदेखा $ 0 लेने के लिए है, ताकि $ @ xargs से सभी तर्क हैं


122
2018-05-23 12:15



आप इस में से एक बाश उपनाम कैसे बनाएंगे? $@ प्रतीत होता है कि तर्क सही तरीके से अनुवाद नहीं कर रहे हैं। - zanegray
@ ज़ेनग्रे - आप उपनाम नहीं बना सकते हैं, लेकिन आप इसे एक फ़ंक्शन बना सकते हैं। प्रयत्न: function vimin () { xargs sh -c 'vim "$@" < /dev/tty' vim; } - Christopher
जीएनयू xargs समाधान कैसे काम करता है, और आपको डमी की आवश्यकता क्यों है, इसकी एक विस्तृत व्याख्या के लिए ignoreme स्ट्रिंग, देखें vi.stackexchange.com/a/17813 - wisbucky
@ ज़ेनग्रे, आप इसे उपनाम बना सकते हैं। उद्धरण मुश्किल हैं। समाधान देखें vi.stackexchange.com/a/17813 - wisbucky


सबसे आसान तरीका:

vim $(find . -name "*foo*")

29
2018-03-08 02:13



मुख्य सवाल "क्यों" था, "इसे कैसे बचें" नहीं, और साढ़े सालों पहले संतुष्टि का उत्तर दिया गया है। - DevSolar
यह निश्चित रूप से, ठीक से काम नहीं करता है जब फ़ाइल नामों में रिक्त स्थान या अन्य विशेष वर्ण होते हैं, और यह एक सुरक्षा जोखिम भी है। - Dejay Clayton
मेरा पसंदीदा उत्तर क्योंकि यह फाइलों को सूचीबद्ध करने वाले प्रत्येक कमांड के लिए काम करता है, न सिर्फ "ढूंढें" या वाइल्डकार्ड। देजय बताते हैं कि इसे थोड़ा विश्वास की आवश्यकता है। - Travis Wilson
यह कई उपयोग मामलों के साथ काम नहीं करेगा xargs के लिए डिज़ाइन किया गया है: उदाहरण के लिए, जब पथ की संख्या बहुत अधिक है (सीसी @ ट्रेविस विल्सन) - Good Person


यदि आप xargs में पाइप करने के बजाए खोजने के लिए -exec विकल्प का उपयोग करते हैं तो यह ठीक काम करना चाहिए। उदा

$ find . -type f -name filename.txt -exec vi {} +


20
2018-03-10 14:31



हू ... चाल है + ("सामान्य" की बजाय \;) सभी पाए गए फाइलों को पाने के लिए एक विम सत्र - एक विकल्प I रखना के बारे में भूलना आप सही हैं, ज़ाहिर है, और उसके लिए +1। मैं उपयोग करता हूं vim $(find ...) बस आदत से बाहर। हालांकि, मैं वास्तव में पूछ रहा था क्यूं कर पाइप ऑपरेशन टर्मिनल को खराब कर देता है, और उसकी व्याख्या के साथ गहराई ने उसे पकड़ लिया। - DevSolar
यह सबसे अच्छा जवाब है और यह बीएसडी / ओएसएक्स / जीएनयू / लिनक्स दोनों पर काम करता है। - kevinarpe
साथ ही, उन फ़ाइलों की सूची प्राप्त करने का एकमात्र तरीका नहीं है जिन्हें विम द्वारा एक साथ संपादित किया जाना है। मैं पैटर्न के साथ सभी फाइलों को खोजने के लिए grep का उपयोग कर सकता हूं और साथ ही साथ उन्हें संपादित करने का प्रयास भी कर सकता हूं। - Chandranshu


इसके बजाए जीएनयू समानांतर का प्रयोग करें:

find . -name "*.txt" | parallel -j1 --tty vim

या यदि आप सभी फ़ाइलों को एक ही बार में खोलना चाहते हैं:

find . -name "*.txt" | parallel -Xj1 --tty vim

यह फ़ाइल नामों के साथ भी सही ढंग से सौदों की तरह है:

My brother's 12" records.txt

अधिक जानने के लिए परिचय वीडियो देखें: http://www.youtube.com/watch?v=OpaiGYxkSuQ


8
2017-09-16 17:45



सर्वव्यापी उपलब्ध नहीं है। अधिकांश दिन मैं सर्वर पर काम कर रहा हूं जहां मुझे अतिरिक्त टूल इंस्टॉल करने की स्वतंत्रता नहीं है। लेकिन वैसे भी संकेत के लिए धन्यवाद। - DevSolar
यदि आपकी बिल्ली 'बिल्ली> फ़ाइल करने की स्वतंत्रता है; chmod + x फ़ाइल 'तो आप जीएनयू समांतर स्थापित कर सकते हैं: यह बस एक पर्ल स्क्रिप्ट है। यदि आप मैन पेज और ऐसे चाहते हैं, तो आप इसे अपने होमएडर के तहत इंस्टॉल कर सकते हैं: ./configure --prefix = $ HOME && make && इंस्टॉल करें - Ole Tange
ठीक है, कोशिश की - लेकिन समानांतर करता है नहीं सभी फाइलें खोलें, यह उन्हें खोलता है उत्तराधिकार में। यह एक साधारण ऑपरेशन के लिए भी एक मुट्ठी भर है। vim $(find . -name "*.txt") सरल है, और आप एक ही समय में सभी फाइलें खोले हैं। - DevSolar
@ डेवसोलर: कुछ हद तक असंबंधित, लेकिन दोनों find | xargs तथा $(find) फ़ाइल नामों में रिक्त स्थान के साथ बड़ी समस्याएं होंगी। - grawity
@ ग्रोथिटी सही है, लेकिन इसके आस-पास कोई आसान तरीका नहीं है (जिसे मैं जानता हूं)। आपको झुकाव शुरू करना होगा $IFS, -print0 और सामान, और फिर आपने एक शॉट कमांड लाइन समाधान का दायरा छोड़ा और उस बिंदु पर पहुंचा जहां आपको एक स्क्रिप्ट के साथ आना चाहिए ... एक कारण है कि फ़ाइल नामों में रिक्त स्थान निराश हैं। - DevSolar