xargs এবং vi - "ইনপুটটি টার্মিনাল থেকে আসে না"


14

php.iniআমার সিস্টেমে আমার প্রায় 10 টি ফাইল রয়েছে যা পুরো জায়গা জুড়ে রয়েছে এবং আমি সেগুলি দিয়ে দ্রুত ব্রাউজ করতে চেয়েছিলাম। আমি এই আদেশটি চেষ্টা করেছি:

locate php.ini | xargs vi

তবে viআমাকে সতর্ক করে Input is not from a terminalএবং তারপরে কনসোলটি সত্যই অদ্ভুত হতে শুরু করে - এর পরে আমাকে :q!প্রস্থান করার জন্য টিপতে হবে viএবং তারপরে ssh অধিবেশন থেকে সংযোগ বিচ্ছিন্ন করতে হবে এবং কনসোলটি আবার স্বাভাবিকভাবে আচরণ করতে পুনরায় সংযোগ করতে হবে।

আমি মনে করি যে এখানে আমি কী ঘটছি তা আমি क्रमबद्धভাবে বুঝতে পেরেছি - মূলত কমান্ডটি viশুরু হওয়ার পরে শেষ হয়নি তাই কমান্ড সম্ভবত শেষ হয়নি এবং viটার্মিনালটি স্বাভাবিক মোডে রয়েছে বলে মনে করে না।

কীভাবে এটি ঠিক করতে হবে আমার কোনও ধারণা নেই। আমি গুগল এবং ইউনিক্স.স্ট্যাকেক্সচেঞ্জ ডট কমকে ভাগ্যের সাথে অনুসন্ধান করেছি।



পার্শ্ব নোট হিসাবে, আপনি resetযখন আপনার টার্মিনালটি খারাপ হয়ে যায় তখন এটি পুনরায় সেট করতে ছুটে যেতে পারেন (আপনাকে এসএসএস সেশন থেকে সংযোগ বিচ্ছিন্ন করতে হবে না)।
উইসবুকি

উত্তর:


12
vi $(locate php.ini)

দ্রষ্টব্য: আপনার ফাইলের পাথগুলিতে স্পেস থাকলে এটিতে সমস্যা থাকবে তবে এটি কার্যকরভাবে আপনার আদেশের সমতুল্য।
এই পরবর্তী সংস্করণটি স্পেসগুলি সঠিকভাবে পরিচালনা করবে তবে এটি আরও জটিল names (ফাইলের নামের নতুন লাইনগুলি এখনও এটি ভেঙে দেবে)

(IFS=$'\n'; vi $(locate php.ini))


ব্যাখ্যা:

যা ঘটছে তা হ'ল প্রোগ্রামগুলি তাদের ফাইল বর্ণনাকারীদের উত্তরাধিকার সূত্রে প্রক্রিয়া থেকে উত্তরাধিকারী। xargsএর STDIN এর STDOUT এর সাথে সংযুক্ত রয়েছে locate, তাই viআসল STDIN আসলে কী আছে তা সম্পর্কে কোনও ধারণা নেই।


2
xargs অসাধারণ, আমার অন্যতম প্রিয় সরঞ্জাম - এটি এমন প্রোগ্রামগুলির সাথে ব্যবহারের জন্য উপযুক্ত নয় যা ডেটা ফিড ব্যতীত অন্য কোনও কিছুর জন্য স্টিডিন ব্যবহার করে। আপনার উত্তর আমি এবং আপনার ব্যাখ্যা অন্য যে, তাই + 1 যাহাই হউক না কেন :)
CA গুলির

@ ক্রেইগস্যান্ডার্স আমি এটি পছন্দ করি না কারণ এটি অপব্যবহার করা (ভুলভাবে ব্যবহার করা) এবং ব্রেকিং শেষ করা খুব সহজ। আমি কখনই এমন কিছুতে প্রবেশ করিনি xargsযা শেল (বা find) দিয়ে সরাসরি করা যায় না এর জন্য আমার অবশ্যই ব্যবহার করতে হয়েছিল । তবে আমি কেসগুলি সম্পর্কে ভাবতে পারি যেখানে এটি সেরা সমাধান হবে। সুতরাং, আপনি যতক্ষণ বুঝতে পেরেছেন কী xargsকরছেন, এটি কীভাবে যুক্তিগুলি বিভক্ত করে, কীভাবে প্রোগ্রামটি চালাচ্ছে ইত্যাদি, এবং এটি সঠিকভাবে ব্যবহার করছে, আমি বলব এর জন্য যান :
প্যাট্রিক

এটি ... | awk '{print $3}' | xargs | sed -e 's/ /+/g' | bc(ফিল্ড 3 এর সমস্ত মান যোগ করতে) এর মতো জিনিসগুলির জন্য বীট করা যায় না । বা sed -e 's/ /|/g'একটি regexp নির্মাণ সঙ্গে । এবং হ্যাঁ, যে কোনও সরঞ্জামের মতো, আপনাকে এটি কীভাবে ব্যবহার করতে হবে এবং এর সীমাবদ্ধতা এবং সতর্কতাগুলি কী তা আপনার জানা দরকার।
সি এ এস

vi $(...)পদ্ধতির এছাড়াও ছাড়া অন্য শেল মধ্যে ওয়াইল্ডকার্ড সঙ্গে একটি সমস্যা আছে zsh
স্টাফেন চেজেলাস

আরও মনে রাখবেন যে xargsহোয়াইটস্পেস ইস্যুর পাশের পদ্ধতির সাথে সিঙ্গল কোট, ডাবল কোট এবং ব্যাকস্ল্যাশ সহ ফাইলের নামও একটি সমস্যা।
স্টাফেন চেজেলাস

10

এই প্রশ্নটি আগে সুপার ব্যবহারকারী ফোরামে জিজ্ঞাসা করা হয়েছিল ।

এই প্রশ্নে @ গুরুতর উত্তর থেকে উদ্ধৃতি:

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

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

Xarg এর ম্যানুয়াল পৃষ্ঠাগুলিতে এটি উল্লেখ করা হয়েছে। ওএসএক্স / বিএসডি থেকে:

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

সুতরাং, ওএসএক্স-এ আপনি নিম্নলিখিত কমান্ডটি ব্যবহার করতে পারেন:

find . -name "php.ini" | xargs -o vim

GNU সংস্করণে সরাসরি কোনও স্যুইচ নেই, এই কমান্ডটি কাজ করবে। ( dummyস্ট্রিংটি অন্তর্ভুক্ত করার বিষয়টি নিশ্চিত করুন , অন্যথায় এটি প্রথম ফাইলটি বাদ দেবে))

find . -name "php.ini" | xargs bash -c '</dev/tty vim "$@"' dummy

উপরের সমাধানগুলি সুপারউজারে সৌজন্যে জাইম ম্যাকগুইগান । এই ত্রুটির জন্য সাইটের অনুসন্ধান করা কোনও ভবিষ্যতের দর্শকদের জন্য তাদের এখানে যুক্ত করা।


3
টিপটির জন্য +1 ধন্যবাদ। আমি বছরের পর বছর ধরে xargs ব্যবহার করে আসছি এবং কখনই লক্ষ্য করিনি যে .... কেবলমাত্র আমার সিস্টেমে ম্যান পৃষ্ঠাটি পরীক্ষা করে দেখেছি, কারণ এটি কোনও GNU xargs বৈশিষ্ট্য নয়। ম্যান পেজটি xargs sh -c 'emacs "$@" < /dev/tty' emacsতারা যা দাবি করে ততটি আরও নমনীয় এবং বহনযোগ্য বিকল্প সরবরাহ করে (যদিও এটি জিএনইউর পক্ষে বৈশিষ্ট্যের তুলনায় বহনযোগ্যতা পছন্দ করা মজাদার)।
ক্যাস

2

GNU findutils, এবং প্রক্রিয়া প্রতিস্থাপনের জন্য সমর্থন সহ একটি শেল (ksh, zsh, bash) দিয়ে আপনি এটি করতে পারেন:

xargs -r0a <(locate -0 php.ini) vi

-a filenameস্ট্যান্ডিনের পরিবর্তে ফাইল তালিকাটি পাস করার ধারণা । ব্যবহারের মাধ্যমে -0নিশ্চিত হয়ে যায় যে ফাইলের নামগুলিতে কী অক্ষর বা অ-অক্ষর থাকতে পারে তা নির্বিশেষে এটি কাজ করে।

সহ zsh, আপনি করতে পারেন:

vi ${(0)"$(locate -0 php.ini)"}

( 0NULs এ বিভক্ত করার জন্য প্যারামিটার সম্প্রসারণের পতাকাটি কোথায়)।

তবে নোট করুন যে এর বিপরীতে কোনও ফাইল না পাওয়া গেলে তর্ক ছাড়াই xargs -rচলমান vi


0

একই সম্পাদকের মধ্যে একাধিক php.ini সম্পাদনা করবেন?

চেষ্টা করুন: vim -o $(locate php.ini)


0

এই ত্রুটিটি ঘটে যখন ভিএমটি চাওয়া হয় এবং এটি টার্মিনালের পরিবর্তে পূর্ববর্তী পাইপলাইনের আউটপুটটির সাথে সংযুক্ত থাকে এবং এটি বিভিন্ন অপ্রত্যাশিত ইনপুট (যেমন এনইউএলএস) গ্রহণ করে। আপনি চালানোর সময় একই ঘটনা ঘটে: vim < /dev/nullসুতরাং resetএই ক্ষেত্রে আদেশটি সাহায্য করে। এটি সুপারভাইজারের মহাকর্ষের দ্বারা ভালভাবে ব্যাখ্যা করা হয়েছে ।

ইউনিক্স / ওএসএক্স এ আপনি প্যারামিটার xargsসহ ব্যবহার করতে পারেন -o:

locate php.ini | xargs -o vim

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

লিনাক্সে নিম্নলিখিত কাজগুলি চেষ্টা করুন:

locate php.ini | xargs -J% sh -c 'vim < /dev/tty $@'

টিটি বরাদ্দের জোর করার parallelপরিবর্তে বিকল্পভাবে জিএনইউ ব্যবহার করুন xargs, উদাহরণস্বরূপ:

locate php.ini | parallel -X --tty vi

দ্রষ্টব্য: parallelইউনিক্স / ওএসএক্সে বিভিন্ন পরামিতি রয়েছে বলে এটি কাজ করবে না এবং এটি tty সমর্থন করে না।

আরও অনেক জনপ্রিয় কমান্ড সিউডো-টিটি বরাদ্দ দেয় (যেমন পছন্দ -tকরে ssh), তাই সাহায্যের জন্য পরীক্ষা করুন।

বিকল্প হিসাবে findসম্পাদনা করার জন্য ফাইলের নাম পাস করার জন্য ব্যবহার করুন, সুতরাং প্রয়োজন নেই xargs, কেবল ব্যবহার করুন -exec, উদাহরণস্বরূপ:

find /etc -name php.ini -exec vim {} +

0

@ পেট্রিকের IFSহ্যাক কেবল বোবা শেল bashএবং এর মতোই প্রয়োজনীয় zshfish ডিফল্টরূপে স্ট্রিংকে নতুন লাইনে বিভক্ত করে।

$ vim (locate php.ini)

Godশ্বর আমাদের সকলকে সাহায্য করুন যদি আমাদের মধ্যে কারওরই নামে একটি নতুন লাইনের সাথে ফাইল থাকে। লিনাক্স ব্যবহারের 17 বছর পরে, আমি এটি একবারও দেখিনি। আমি কেবল স্ক্রিপ্টগুলির জন্য তাদের মধ্যে নতুন লাইনের সাহায্যে ফাইলনামগুলিকে সমর্থন করতে বিরক্ত করতাম যে যাই হোন না কেন, তবে এর মতো স্ক্রিপ্টগুলি সম্ভবত ভিম ইন্টারেক্টিভভাবে চলছে না।


zshডিফল্টরূপে এসপিসি, ট্যাব, এনএল এবং এনএলএতে বিভক্ত হয়। এটি যে জিনিসটির সাথে তুলনা করে না তা bashহ'ল ফলাফলকে গ্লোববিং করে তোলে তাই ফাইলের নামের ওয়াইল্ডকার্ড অক্ষরগুলি কোনও সমস্যা নয়। ইন zsh, আপনি করতে চাই IFS=$'\0'; vi $(locate -0 php.ini)বা আমি আমার উত্তর দেখানো vi ${(0)"$(locate -0 php.ini)"}একটি সুনির্দিষ্ট বিভাজন অপারেটর জন্য। এছাড়াও tcsh এর নোট করুনvi "`locate php.ini`"
স্টাফেন চাজেলা

ওহ, বাজে। ঠিক আছে এটি কাজ করে: $ f='not there'<ret>$ ls $f<ret>তবে এটি করে না: এলএস echo not there। ঠিক আছে দেখে মনে হচ্ছে আমার এটি কিছুটা আপডেট করা দরকার।
এনজিমেটিক্যাল

হ্যাঁ, zsh যখন আপনি করবেন তখন সঠিক জিনিসটি করেন না ls "$(echo test; echo other test)"। কেবল মাছই সঠিক কাজ করে।
এনজিমেটিক্যাল

ধরে নিচ্ছি আপনার উদ্ধৃতি ব্যতীত একই অর্থ, এটি "সঠিক" নয়, এটি লাইনে বিভক্ত হয়ে গেছে, এটি কেবল অন্যরকম পছন্দ। zsh ডিফল্টরূপে (সমস্ত অন্যান্য শাঁসের মতো) শব্দের উপর বিভক্ত হয় এবং লাইন বা NUL গুলি $IFSস্পষ্ট অপারেটরগুলির মাধ্যমে বা স্পেসিফিক অপারেটরগুলির মাধ্যমে ( fএবং 0প্যারামিটার এক্সপেনশন ফ্ল্যাগ) বিভক্ত করতে বলা যেতে পারে । স্বেচ্ছাসেবী ফাইল নামগুলির জন্য, শব্দের দ্বারা বিভক্ত হওয়া বা লাইন দ্বারা বিভাজন করা সমানই ভুল , আপনাকে NUL এ বিভক্ত হওয়া বা কিছু এনকোডিং পার্স করা দরকার, যা fishকরতে পারে না। ইন zsh, এটি IFS=$'\0'; ls -ld -- $(printf '%s\0' "$file1" "$file2")বাls -ld -- ${(0)"$(printf '%s\0' "$file1" "$file2")"}
স্টাফেন চ্যাজেলাস

সাধরণ। নতুন লাইনে বিভক্ত করা যথেষ্ট ভাল। উত্তরটি বলার মতো, ফাইলনামগুলিতে নিউলাইনগুলি অত্যন্ত বিরল। আমি আক্ষরিকভাবে এটি 17 বছরে কখনও দেখিনি। এবং নিউলাইনগুলি নুলের চেয়ে আরও সুবিধাজনক বিভাজক।
এনজিমেটিক্যাল

0

একটি দ্রুত উপায় এটা করতে হবে, অভিমানী ফাইল পাথ কেউই নিশ্চিত করতে পারে না ধারণ SPC, ট্যাব, এন এল, *, ?, [অক্ষর (এছাড়াও \এবং {...}কিছু শাঁস মধ্যে) ব্যাক-এঁটেল পোকা ব্যবহার করা (ওরফে কবর কথা) পূর্বে কমান্ড চালানো আর একটি কমান্ড চলছে।

যেমন

vi `find / -type f -name 'php.ini'`

পিছনে টিক্সের মধ্যে থাকা কমান্ডটি প্রথমে কার্যকর করবে। এরপরে অন্তর্ভুক্ত কমান্ডের আউটপুট ব্যাক-টিক্সের আগে বর্ণিত কমান্ড দ্বারা কার্যকর করা হয়।

উদাহরণস্বরূপ, উপরের লাইনে, find / -type f -name 'php.ini'কমান্ডটি প্রথমে কার্যকর করবে, আউটপুট প্রেরণ viকরবে এবং তারপরে সেই আউটপুটটিতে স্প্লিট + গ্লোব প্রয়োগের ফলস্বরূপ কার্যকর করা হবে।


3
ব্যাক-টিকগুলি একক-কোটের জন্য খুব সহজেই বিভ্রান্ত হয়। $(find ...)পরিবর্তে ব্যবহার করুন।
ক্যাস

1
এটি অনুমান করা ফাইলের নামগুলিতে ফাঁকা স্থান এবং / অথবা নিউলাইনগুলিতেও ভেঙে যাবে?
cwd

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