سؤال استدعاء vi من خلال البحث | xargs يكسر طرفي. لماذا ا؟


عند الاستدعاء vim عبر find | xargs، مثله:

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

تحصل على تحذير حول

Input is not from a terminal

ومحطة مع السلوك المكسور إلى حد كبير بعد ذلك. لماذا هذا؟


123
2017-09-15 16:26


الأصل


ملاحظة جانبية: يمكنك إجراء هذه العملية بالكامل داخل vim ، وليس باستخدام find أو xargs على الاطلاق. فتح vim مع أي الحجج ، ثم تشغيل :args **/*.txt<CR>لتعيين حجج vim من داخل المحرر. - Trevor Powell
TrevorPowell: في كل هذه السنوات ، لم يتوقف vim عن تدهشني. - DevSolar
ذات صلة: grep -l .. | xargs vim يولد تحذيرًا ، لماذا؟ في يونيكس SE - kenorb
ذات صلة: المحطة الطرفية borked بعد استدعاء vim مع xargs في Vim SE. - kenorb
تقرير علة GitHub: vim لا يعالج STDIN set to / 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 /

تتوقع Vim أن تكون stdin الخاص بها هو نفس جهاز التحكم الخاص بها ، ويقوم بتنفيذ العديد من الأجهزة الطرفية IOCTLعلى ستدين مباشرة. عند الانتهاء /dev/null (أو أي واصف ملف غير tty) ، تلك ioctls لا معنى لها والعودة ENOTTY ، الذي يتم تجاهله بصمت.

  • تخميني في سبب أكثر تحديدًا: عند بدء التشغيل يقرأ Vim ويتذكر إعدادات المحطة القديمة ، ويعيدها عند الخروج. في حالتنا ، عندما يتم طلب "الإعدادات القديمة" لـ fd غير مدقق (واصف ملف) ، يتلقى Vim جميع القيم فارغة وتعطل جميع الخيارات ، ويضع نفسه بلا مبالاة على جهازك.

    يمكنك رؤية هذا عن طريق الجري vim < /dev/nullللخروج منه ، ثم الجري sttyوالتي ستنتج الكثير من <undef>الصورة. على لينكس ، قيد التشغيل stty sane سيجعل الجهاز صالحًا للاستخدام مرة أخرى (على الرغم من ذلك سوف فقدوا خيارات مثل iutf8، وربما تسبب مضايقات طفيفة في وقت لاحق).

هل يمكن اعتبار هذا خطأ في فيم ، منذ ذلك الحين يستطيع افتح /dev/tty للتحكم في المحطة ، ولكن لا. (في مرحلة ما أثناء بدء التشغيل ، يقوم Vim بتكرار stderr إلى stdin ، والذي يسمح له بقراءة أوامر الإدخال الخاصة بك - من fd مفتوح للكتابة - ولكن حتى لا يتم ذلك في وقت مبكر بما فيه الكفاية.)


85
2017-09-15 16:41



... مع تزدهر. شكرا جزيلا! - DevSolar
+1 ، و TL ؛ الناس DR تشغيل فقط stty sane - rahmanisback
rahmanisback: قدمت الإجابات الأخرى ، بالإضافة إلى تعليق تريفور ، كل الطرق لتجنب كسر الطرفية في المقام الأول. قبلت إجابة الجرأة ، لأن سؤالي كان "لماذا" ، وليس "كيف أتجنب" - وهذا ما نغطيه سؤال آخر هذا في الواقع ولدت هذا. - DevSolar
أفهمت DevSolar ، ولكن التفكير في الناس المحبطين مثلي الذين google فقط كيفية التخلص من هذا السلوك في حين - لسوء الحظ - لديها ما يكفي من الوقت الآن لدراسة "لماذا" ، وهو أمر مثير للاهتمام على الرغم من ذلك. - rahmanisback
عندما تتوقف طرفي ، مثل هذا ، استخدمه reset بدلا من stty sane ويعمل بشكل جيد بعد ذلك. - Capi Etheriel


متابعًا من إجابة الجرأة ، xargs نقاط stdin إلى /dev/null


من OSX / BSD man xargs

إعادة فتح stdin كما / dev / tty في عملية التابعة
        قبل تنفيذ الأمر. وهذا مفيد
        إذا كنت تريد xargs لتشغيل تطبيق تفاعلي.

وبالتالي يجب أن يعمل السطر التالي من التعليمات البرمجية:

تجد . -name "* .txt" | xargs -o vim

لجنو man xargs لا يوجد علم ، ولكن يمكننا أن نمرر بشكل صريح في / dev / tty لحل المشكلة:

تجد . -name "* .txt" | xargs bash -c '</ dev / tty vim "$ @" "ignoreme

الجُهَوْر موجود هناك ليأخذ $ 0 ، بحيث $ @ هو كل الحجج من xargs


122
2018-05-23 12:15



كيف يمكنك إنشاء bash alias للخروج من هذا؟ $@ لا يبدو أن ترجمة الحجج بشكل صحيح. - zanegray
zanegray - لا يمكنك إنشاء اسم مستعار ، ولكن يمكنك جعله وظيفة. محاولة: function vimin () { xargs sh -c 'vim "$@" < /dev/tty' vim; } - Christopher
للحصول على شرح مفصل لكيفية عمل حل GNU xargs ، ولماذا تحتاج إلى الدمية ignoreme سلسلة ، انظر vi.stackexchange.com/a/17813 - wisbucky
zanegray ، يمكنك جعله مستعارًا. الاقتباسات صعبة. انظر الحل في vi.stackexchange.com/a/17813 - wisbucky


أسهل طريقة:

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

29
2018-03-08 02:13



كان السؤال الرئيسي هو "لماذا" ، وليس "كيفية تجنب ذلك" ، وتمت الإجابة عليه بالرضا منذ عامين ونصف. - DevSolar
هذا ، بالطبع ، لا يعمل بشكل صحيح عندما تحتوي أسماء الملفات على مسافات أو أحرف خاصة أخرى ، وهو أيضاً مخاطرة أمان. - Dejay Clayton
إجابتي المفضلة لأنها تعمل مع كل أمر يسرد الملفات ، وليس فقط "find" أو wildcards. إنها تتطلب القليل من الثقة ، كما يشير ديجاي. - Travis Wilson
هذا لن يعمل مع العديد من حالات الاستخدام تم تصميم xargs من أجل: على سبيل المثال ، عندما يكون عدد المسارات مرتفعًا جدًا (ccTravisWilson) - Good Person


يجب أن تعمل على ما يرام إذا كنت تستخدم الخيار -exec في العثور بدلاً من piping إلى xargs. منها مثلا

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


20
2018-03-10 14:31



هوة ... الخدعة هناك + (بدلاً من "المعتاد" \;) للحصول على جميع الملفات الموجودة واحد جلسة فيم - خيار أنا احتفظ نسيان. أنت على حق ، بالطبع ، +1 لإجراء ذلك. أنا أستعمل vim $(find ...) ببساطة من العادة. ومع ذلك ، كنت أطلب بالفعل لماذا ا عملية المسمار الأنابيب تصل المحطة ، و مسمر grawity مع شرحه. - DevSolar
هذا هو أفضل إجابة ويعمل على كل من BSD / OSX / GNU / Linux. - kevinarpe
كما أن البحث ليس الطريقة الوحيدة للحصول على قائمة بالملفات التي يجب تحريرها في وقت واحد بواسطة vim. يمكنني استخدام grep للعثور على جميع الملفات ذات النمط ومحاولة تعديلها في نفس الوقت أيضًا. - Chandranshu


استخدم GNU Parallel بدلاً من ذلك:

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
إذا كان لديك الحرية في عمل ملف "cat" ؛ chmod + x file "ثم يمكنك تثبيت GNU Parallel: إنه ببساطة نص برل. إذا كنت تريد صفحات رجل ومثل هذا ، يمكنك تثبيته تحت homedir: ./configure --prefix = $ HOME && make && make install - Ole Tange
حسنا ، حاول ذلك - ولكن بالتوازي يفعل ليس فتح جميع الملفات ، فإنه يفتح لهم بنجاح. انها أيضا الفم تماما لعملية بسيطة. vim $(find . -name "*.txt") هو أبسط ، وتحصل على جميع الملفات مفتوحة في وقت واحد. - DevSolar
DevSolar: لا علاقة لها ببعضها البعض ، ولكن كليهما find | xargs و $(find) سوف تواجه مشاكل كبيرة مع مسافات في أسماء الملفات. - grawity
grawity صحيحة ، ولكن ليس هناك طريقة سهلة حولها (التي أعرفها). عليك أن تبدأ بالتلاعب $IFS، -print0 والأشياء ، ثم تركت مجال الحل سطر واحد بالرصاص ، ووصلت إلى نقطة حيث يجب عليك التوصل إلى برنامج نصي ... هناك سبب لماذا لا يتم تثبيط الفراغات في أسماء الملفات. - DevSolar