সন্ধানের মাধ্যমে vi চালাচ্ছি | xargs আমার টার্মিনালটি ভেঙে দেয়। কেন?


137

যখন অনুরোধ করা vimহয় find | xargs, এটির মতো:

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

আপনি সম্পর্কে একটি সতর্কতা পেতে

Input is not from a terminal

এবং পরবর্তীতে বেশ অনেকটা ভাঙা আচরণ সহ একটি টার্মিনাল। তা কেন?


11
পার্শ্ব দ্রষ্টব্য: আপনি পুরোপুরি এই অপারেশনটি vim এর মধ্যেই ব্যবহার করতে পারেন, ব্যবহার findবা একেবারেই করবেন না xargs। কোনও যুক্তি ছাড়াই ভিমটি খুলুন, তারপরে :args **/*.txt<CR>সম্পাদকের ভিতরে থেকে ভিমের যুক্তিগুলি সেট করতে চালান run
ট্রেভর পাওয়েল

3
@ ট্র্যাভারপোয়েল: এই সমস্ত বছরে, ভিম কখনও আমাকে অবাক করে দেয়নি।
দেবসোলার



উত্তর:


100

আপনি যখন কোনও প্রোগ্রামের মাধ্যমে xargsআবেদন করেন তখন প্রোগ্রামটির স্টিডিন (স্ট্যান্ডার্ড ইনপুট) নির্দেশ করে /dev/null। (যেহেতু xargs মূল স্টিডিনটি জানে না , তাই এটি পরবর্তী সেরা কাজটি করে)

$ সত্য | xargs filan -s
    0 ক্রডদেব / দেব / নাল
    1 টিটি / দেব / পিটিএস / 1
    2 টিটি / দেব / পিটিএস / 1

$ সত্য | xargs ls -l / dev / fd /

ভিম তার স্ট্যান্ডিনটি তার নিয়ন্ত্রণকারী টার্মিনালের মতোই প্রত্যাশা করে এবং স্ট্যান্ডিনে সরাসরি টার্মিনাল-সম্পর্কিত বিভিন্ন আইওসিটিএল সম্পাদন করে। যখন সম্পন্ন /dev/null(অথবা কোনো অ-TTY ফাইল বর্ণনাকারী), সেই ioctls অর্থহীন এবং ENOTTY, যা চুপটি উপেক্ষিত পরার ফিরে যান।

  • আরও অনুমানযোগ্য কারণ নিয়ে আমার অনুমান: প্রারম্ভকালে ভিম পুরানো টার্মিনাল সেটিংস পড়ে এবং মনে রাখে এবং প্রস্থান করার সময় সেগুলি পুনরুদ্ধার করে। আমাদের পরিস্থিতিতে যখন "পুরানো সেটিংস" টি নন-টিটিডি এফডি (ফাইল বর্ণনাকারী) এর জন্য অনুরোধ করা হয়, তখন ভিম সমস্ত মান খালি এবং সমস্ত বিকল্প অক্ষম করে এবং অযত্নে আপনার টার্মিনালে সেট করে।

    আপনি vim < /dev/nullএটি চালিয়ে , প্রস্থান করে, এবং তারপরে চালিয়ে দেখতে পাচ্ছেন sttyযা পুরো প্রচুর পরিমাণে আউটপুট দেয় <undef>। লিনাক্স এ, চলমান stty saneআবার টার্মিনাল ব্যবস্থা গ্রহণ করব (যদিও এটা হবে এমন অপশন হারিয়েছে যেমন iutf8, সম্ভবত ছোটখাট annoyances পরে ঘটাচ্ছে)।

আপনি এটি ভিমে একটি বাগ বিবেচনা করতে পারেন , যেহেতু এটি /dev/ttyটার্মিনাল নিয়ন্ত্রণের জন্য খুলতে পারে , কিন্তু তা নয়। (প্রারম্ভকালে কোনও সময়, ভিম তার স্টাডারকে স্টিডিনে নকল করে, যা এটি আপনার ইনপুট কমান্ডগুলি পড়তে দেয় - লেখার জন্য খোলার একটি এফডি থেকে - তবে এটি পর্যাপ্ত পর্যায়ে করা হয় না))


20
+1, এবং টিএল-এর জন্য; ডিআর লোকেরা কেবল চালাবেনstty sane
ডক_আইডি

@ রহমানিসব্যাক: অন্যান্য উত্তরগুলি, এবং ট্রেভরের মন্তব্য, প্রথম স্থানে টার্মিনাল ভাঙ্গন এড়াতে সমস্ত উপায় সরবরাহ করেছিল। আমি মহাকর্ষের জবাব মেনে নিয়েছি, কারণ আমার প্রশ্নটি "কেন", "কীভাবে এড়াতে হবে" নয় - এটি অন্য একটি প্রশ্ন দ্বারা আবৃত ছিল যা আসলে এটির উত্থাপন করেছিল
দেবসোলার

@ ডেভসোলার বুঝতে পেরেছেন, তবে আমার মতো হতাশ ব্যক্তিদের সম্পর্কে চিন্তা করুন যারা দুর্ভাগ্যজনকভাবে নয় এমন সময়ে কীভাবে এই আচরণ থেকে মুক্তি পেতে পারে তা গুগল করেন - "কেন" অধ্যয়ন করার জন্য এই মুহুর্তে যথেষ্ট সময় আছে যা তবুও খুব আকর্ষণীয়।
doc_id

4
যখন আমার টার্মিনালটি ভেঙে যায়, আমি এর resetপরিবর্তে ব্যবহার করি stty saneএবং এটি পরে ঠিক কাজ করে।
ক্যাপী ইথেরিয়েল

136

(মহাকর্ষের ব্যাখ্যা অনুসরণ করে, এটি xargsনির্দেশ stdinকরে /dev/null))

এই সমস্যার সমাধানটি হল -oপ্যারামিটারটি যুক্ত করা xargs। থেকে man xargs:

-o

      /dev/ttyকমান্ড কার্যকর করার আগে শিশু প্রক্রিয়া হিসাবে স্টিডিন পুনরায় খুলুন । আপনি যদি xargsইন্টারেক্টিভ অ্যাপ্লিকেশন চালাতে চান তবে এটি কার্যকর ।

সুতরাং, নিম্নলিখিত কোডের লাইনটি আপনার পক্ষে কাজ করা উচিত:

খুঁজে। -নাম "* .txt" | xargs -o vim

জিএনইউ xargs এই এক্সটেনশনটিকে 2017 সালে প্রকাশের পরে (দীর্ঘ বিকল্পের নাম সহ --open-tty) সমর্থন করে।

Xargs এর পুরানো বা অন্যান্য সংস্করণগুলির জন্য, আপনি /dev/ttyসমস্যাটি সমাধান করতে সুস্পষ্টভাবে প্রবেশ করতে পারেন :

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

(এখানে ignoreme$ 0 নিতে হবে, যাতে $ @ সমস্ত যুক্তি xargs থেকে আসে))


2
আপনি এটির বাইরে কীভাবে একটি বাশ ওরফে তৈরি করবেন? $@যুক্তিগুলি সঠিকভাবে অনুবাদ করা বলে মনে হচ্ছে না।
zanegray

1
@ জেনেগ্রে - আপনি একটি উপনাম তৈরি করতে পারবেন না, তবে আপনি এটি একটি ফাংশন করতে পারেন। চেষ্টা করুন:function vimin () { xargs sh -c 'vim "$@" < /dev/tty' vim; }
ক্রিস্টোফার

জিএনইউ xargs সমাধান কীভাবে কাজ করে এবং ডামি ignoremeস্ট্রিংয়ের প্রয়োজন কেন তার বিশদ ব্যাখ্যার জন্য vi.stackexchange.com/a/17813
উইসবাকী

@ জেনেগ্রে, আপনি এটি একটি উপাধি তৈরি করতে পারেন। উদ্ধৃতিগুলি জটিল। Vi.stackexchange.com/a/17813
উইসবাকী

The -J, -o, -P and -R options are non-standard FreeBSD extensions which may not be available on other operating systems.(এটি আমার জন্য ম্যাকোজে উপলভ্য ছিল না কারণ আমি হোমব্রিউ থেকে জার্গাগগুলি ইনস্টল করেছি (জিএনইউ ওয়ান))
লোকালহোস্টডটদেব

33

সহজতম পথ:

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

5
মূল প্রশ্নটি "কেন", "কীভাবে এড়ানো যায়" নয় এবং আড়াই বছর আগে এটির সন্তুষ্টির জবাব দেওয়া হয়েছিল।
দেবসোলার

5
এটি যখন অবশ্যই ফাইলের নামগুলিতে স্পেস বা অন্যান্য বিশেষ অক্ষর ধারণ করে ঠিকঠাক কাজ করে না, এবং এটি সুরক্ষা ঝুঁকিও হয়।
দেজে ক্লেটন

1
আমার প্রিয় উত্তর কারণ এটি প্রতিটি কমান্ডের জন্য কাজ করে যা কেবল "সন্ধান" বা ওয়াইল্ডকার্ড নয়, ফাইলগুলি তালিকাভুক্ত করে। দেযে উল্লেখ করেছেন বলে এর জন্য কিছুটা আস্থা দরকার।
ট্র্যাভিস উইলসন

1
Xargs এর জন্য ডিজাইন করা অনেকগুলি ব্যবহারের ক্ষেত্রে এটি কাজ করবে না: উদাহরণস্বরূপ, যখন পাথের সংখ্যা খুব বেশি থাকে (সিসি @ ট্র্যাভিস উইলসন)
শুভ ব্যক্তি

21

আপনি যদি xargs এ পাইপের পরিবর্তে সন্ধানে -exec বিকল্পটি ব্যবহার করেন তবে এটি ঠিক কাজ করা উচিত।

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

2
হাহ ... কৌতুক আছে +(পরিবর্তে এর "স্বাভাবিক" \;) মধ্যে সব পাওয়া ফাইল পেতে এক একটি বিকল্প আমি - তেজ অধিবেশন রাখা সম্পর্কে বিস্মরণ। আপনি অবশ্যই ঠিক বলেছেন, এবং এটির জন্য +1। আমি vim $(find ...)কেবল অভ্যাসের বাইরে ব্যবহার করি । তবে, আমি আসলেই জিজ্ঞাসা করছিলাম কেন পাইপ অপারেশন টার্মিনালটি আপ করে দেয় এবং গুরুতরতা তার ব্যাখ্যা দিয়ে পেরেক দিয়েছিল।
দেবসোলার

2
এটি সেরা উত্তর এবং এটি BSD / OSX / GNU / লিনাক্স উভয় ক্ষেত্রেই কাজ করে।
কেভিনার্পে

1
এছাড়াও, ভিএম দ্বারা একসাথে সম্পাদনা করতে হবে এমন ফাইলগুলির তালিকা পাওয়ার একমাত্র উপায় নয়। আমি একটি প্যাটার্ন সহ সমস্ত ফাইল সন্ধান করতে গ্রেপ ব্যবহার করতে পারি এবং পাশাপাশি একই সময়ে এডিট করার চেষ্টা করতে পারি।
চন্দ্রনশু

8

পরিবর্তে GNU সমান্তরাল ব্যবহার করুন:

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


1
সর্বব্যাপী উপলব্ধ নয়। বেশিরভাগ দিন আমি সার্ভারগুলিতে কাজ করছি যেখানে অতিরিক্ত সরঞ্জাম ইনস্টল করার আমি স্বাধীনতা পাচ্ছি না। তবে যাইহোক ইঙ্গিতটির জন্য ধন্যবাদ।
দেবসোলার

আপনার যদি 'বিড়াল> ফাইল করার স্বাধীনতা থাকে; chmod + x ফাইল 'তারপরে আপনি GNU সমান্তরাল ইনস্টল করতে পারেন: এটি কেবল পার্ল স্ক্রিপ্ট। আপনি যদি ম্যান পেজ এবং এগুলি চান তবে আপনি এটি আপনার হোমডিরের অধীনে ইনস্টল করতে পারেন: ./ কনফিগার - প্রিফিক্স = $ হোম অ্যান্ড অ্যান্ড মেক অ্যান্ড মেক ইনস্টল
ওলে

2
ঠিক আছে, চেষ্টা করে দেখুন - তবে সমান্তরাল সমস্ত ফাইল খোলেন না , এটি পর পর তাদের খোলায় । এটি একটি সাধারণ অপারেশনের জন্যও বেশ মুখের। vim $(find . -name "*.txt")সহজ, এবং আপনি একবারে সমস্ত ফাইল খোলেন।
দেবসোলার

5
@ ডেভসোলার: কিছুটা সম্পর্কহীন, তবে উভয়ই find | xargsএবং $(find)ফাইলের নামের ফাঁকে ফাঁকে বড় সমস্যা হবে।
মাধ্যাকর্ষণ

2
@ গ্রায়েটি সঠিক, তবে এর চারপাশে কোনও সহজ উপায় নেই (যা আমি জানি)। আপনাকে ঝাঁকুনি $IFS, -print0এবং স্টাফ দিয়ে শুরু করতে হবে এবং তারপরে আপনি একটি শট কমান্ড লাইন সমাধানের ক্ষেত্র ছেড়ে চলে এসেছিলেন এবং এমন একটি জায়গায় পৌঁছেছিলেন যেখানে আপনার স্ক্রিপ্ট নিয়ে আসা উচিত ... ফাইলনামগুলির ফাঁকা স্থান নিরুত্সাহ করার কারণ রয়েছে there's ।
দেবসোলার

0

সম্ভবত সেরা না তবে এটি এখানে আমার ব্যবহৃত স্ক্রিপ্ট (নাম দেওয়া vim-open):

#!/usr/bin/env ruby

require 'shellwords'

inputs = (ARGV + (STDIN.tty? ? [] : STDIN.to_a)).map(&:strip)
exec("</dev/tty vim #{inputs.flatten.shelljoin}")

উদাহরণস্বরূপ vim-open a b cএবং সঙ্গে কাজ করবেls | vim-open


বেশ কয়েকটি অন্যান্য উত্তর হিসাবে, নোট করুন যে আসল প্রশ্নটি "কেন", "এটি কীভাবে এড়ানো যায়" নয়। (যার জন্য আমি এখনও আমার প্রশ্নের অধীনে ট্রেভরের মন্তব্যে সবচেয়ে
দৃ way়
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.