আপনি কীভাবে বাশের দুটি পাইপলাইন আলাদা করতে পারেন?


143

আপনি কিভাবে পারেন বিবিধতা ব্যাশ মধ্যে অস্থায়ী ফাইল ব্যবহার না করেই দুই পাইপলাইনগুলি? বলুন আপনার কাছে দুটি কমান্ড পাইপলাইন রয়েছে:

foo | bar
baz | quux

এবং আপনি diffতাদের ফলাফল খুঁজে পেতে চান । একটি সমাধান স্পষ্টতই হবে:

foo | bar > /tmp/a
baz | quux > /tmp/b
diff /tmp/a /tmp/b

বাশে অস্থায়ী ফাইলগুলি ব্যবহার না করে কি এটি করা সম্ভব? পৃথক পাইপলাইনগুলির মধ্যে একটিতে পাইপ দিয়ে আপনি একটি অস্থায়ী ফাইল থেকে মুক্তি পেতে পারেন:

foo | bar > /tmp/a
baz | quux | diff /tmp/a -

তবে আপনি উভয় পাইপলাইন একই সাথে আলাদা করতে পারবেন না (কোনও স্পষ্ট পদ্ধতিতে নয়, অন্তত)। /dev/fdঅস্থায়ী ফাইলগুলি ব্যবহার না করে এটি করার জন্য কিছু চালাক কৌশল রয়েছে ?

উত্তর:


146

2 টিএমপি ফাইলযুক্ত একটি লাইন (আপনি যা চান তা নয়) হ'ল:

 foo | bar > file1.txt && baz | quux > file2.txt && diff file1.txt file2.txt

সঙ্গে ব্যাশ , আপনি যদিও চেষ্টা করতে পারেন:

 diff <(foo | bar) <(baz | quux)

 foo | bar | diff - <(baz | quux)  # or only use process substitution once

২ য় সংস্করণটি আরও স্পষ্টভাবে মনে করিয়ে দেবে যে দুটি ইনপুট পরিবর্তে
-- /dev/stdinবনাম ++ /dev/fd/63বা কিছু দেখিয়ে কোন ইনপুটটি ছিল ।


এমনকি ফাইল সিস্টেমে কোনও নামযুক্ত পাইপও উপস্থিত হবে না, কমপক্ষে ওএসে যেখানে ব্যাশ ফাইলের নাম ব্যবহার করে প্রক্রিয়া প্রতিস্থাপন /dev/fd/63প্রয়োগ করতে পারে যা কমান্ডটি খুলতে পারে এবং ইতিমধ্যে খোলা ফাইল বর্ণনাকারীর কাছ থেকে আসলে পড়তে পারে এমন ফাইল ফাইল পেতে পারে যা বাশ সেট করে কমান্ড কার্যকর করার আগে আপ। (যেমন বাশ pipe(2)কাঁটাচামড়ার আগে ব্যবহার করে , এবং তারপরে এফডি 63৩-তে dup2আউটপুট থেকে quuxইনপুট ফাইলের বর্ণনাকারীর দিকে পুনর্নির্দেশের জন্য diff))

কোনও "যাদুকরী" /dev/fdবা সিস্টেমে /proc/self/fdবাশ প্রক্রিয়া প্রতিস্থাপন বাস্তবায়নের জন্য নামযুক্ত পাইপ ব্যবহার করতে পারে তবে অস্থায়ী ফাইলগুলির মতো এটি কমপক্ষে সেগুলি নিজেই পরিচালনা করবে এবং আপনার ডেটা ফাইল সিস্টেমে লিখিত হবে না।

আপনি বাশ কীভাবে ফাইলনামটি echo <(true)পড়ার পরিবর্তে ফাইলের নাম মুদ্রণের সাথে বিকল্প বিকল্প প্রয়োগ করে তা পরীক্ষা করতে পারেন । এটি /dev/fd/63একটি সাধারণ লিনাক্স সিস্টেমে মুদ্রণ করে। বা সিস্টেম ব্যাশকে ঠিক কী ব্যবহার করে সে সম্পর্কে আরও তথ্যের জন্য, লিনাক্স সিস্টেমে এই কমান্ডটি ফাইল এবং ফাইল-বিবরণকারী সিস্টেম কলগুলি সনাক্ত করবে

strace -f -efile,desc,clone,execve bash -c '/bin/true | diff -u - <(/bin/true)'

বাশ ছাড়া, আপনি একটি নামযুক্ত পাইপ তৈরি করতে পারেন । ব্যবহার করুন -জানাতে diffstdin থেকে এক ইনপুট পড়তে, এবং অন্যান্য নামকরণ নল ব্যবহার করার জন্য:

mkfifo file1_pipe.txt
foo|bar > file1_pipe.txt && baz | quux | diff file1_pipe.txt - && rm file1_pipe.txt

মনে রাখবেন আপনি যা করতে পারেন শুধুমাত্র নল এক আউটপুট করতে একাধিক ইনপুট টী বর্ণের নাম আদেশের সঙ্গে:

ls *.txt | tee /dev/tty txtlist.txt 

উপরের কমান্ডটি টার্মিনালে ls * .txt এর আউটপুট প্রদর্শন করে এবং এটি পাঠ্য ফাইল txtlist.txt এ আউটপুট দেয়।

তবে প্রক্রিয়া প্রতিস্থাপনের সাথে আপনি teeএকই ডেটাটিকে একাধিক পাইপলাইনে ফিড করতে ব্যবহার করতে পারেন :

cat *.txt | tee >(foo | bar > result1.txt)  >(baz | quux > result2.txt) | foobar

5
এমনকি ব্যাশ ছাড়া, আপনি অস্থায়ী FIFO এর ব্যবহার করতে পারেনmkfifo a; cmd >a& cmd2|diff a -; rm a
unhammer

আপনি args এক জন্য একটি নিয়মিত পাইপ ব্যবহার করতে পারেন: pipeline1 | diff -u - <(pipeline2)। তারপরে আউটপুটটি আরও স্পষ্টভাবে মনে করিয়ে দেবে যে দুটি ইনপুট পরিবর্তে -- /dev/stdinবনাম ++ /dev/fd/67বা কিছু দেখিয়ে কোন ইনপুটটি ছিল ।
পিটার কর্ডস

প্রক্রিয়া বিকল্প ( foo <( pipe )) ফাইল সিস্টেম পরিবর্তন করে না। পাইপ বেনামে ; ফাইল সিস্টেমে এর কোনও নাম নেই । শেল pipeসিস্টেম কলটি এটি তৈরি করতে ব্যবহার করে, না mkfifo। ব্যবহার করুন strace -f -efile,desc,clone,execve bash -c '/bin/true | diff -u - <(/bin/true)'ট্রেস ফাইল এবং ফাইল-বর্ণনাকারী সিস্টেম কল যদি আপনি নিজের জন্য দেখতে চাই। লিনাক্স /dev/fd/63-এ /procভার্চুয়াল ফাইল সিস্টেমের অংশ ; এটিতে প্রতিটি ফাইল বর্ণনাকারীর জন্য স্বয়ংক্রিয়ভাবে এন্ট্রি রয়েছে এবং এটি সামগ্রীর অনুলিপি নয়। সুতরাং আপনি এটি "অস্থায়ী ফাইল" কল করতে পারবেন না যদি না foo 3<bar.txtগণনা করা হয়
পিটার কর্ডস

@ পিটারকর্ডস ভাল পয়েন্টসমূহ আরও দৃশ্যমানতার জন্য আমি আপনার মন্তব্যে উত্তরে অন্তর্ভুক্ত করেছি।
ভনসি

1
@ পিটারকর্ডস আমি আপনাকে যে কোনও সম্পাদনা ছেড়ে দেব: স্ট্যাক ওভারফ্লো আকর্ষণীয় করে তোলে: যে কোনও উত্তর একটি "সমাধান" করতে পারে।
ভনসি

127

বাশে আপনি প্রথম স্থানের মধ্যে পাইপলাইনটি বন্ধ করে পৃথকভাবে কমান্ড পাইপলাইনগুলি সম্পাদন করতে সাব-শেলগুলি ব্যবহার করতে পারেন। এরপরে আপনি <বেনামে নামযুক্ত পাইপ তৈরি করতে প্রিফিক্স করতে পারেন যা আপনি পরে আলাদা করতে পারেন।

উদাহরণ স্বরূপ:

diff <(foo | bar) <(baz | quux)

বেনামে নামযুক্ত পাইপগুলি ব্যাশ দ্বারা পরিচালিত হয় যাতে সেগুলি স্বয়ংক্রিয়ভাবে তৈরি এবং ধ্বংস হয়ে যায় (অস্থায়ী ফাইলগুলির বিপরীতে)।


1
অজ্ঞাতনামা ব্যাচ - একই সমাধানে আমার প্রতিক্রিয়াটির চেয়ে অনেক বেশি বিশদ। +1
ভোনসি


5

এই পৃষ্ঠায় আগত কিছু লোক হয়ত লাইন-বাই-লাইন পার্থক্যের সন্ধান করছেন, যার পরিবর্তে commবা grep -fব্যবহার করা উচিত।

একটি বিষয় উল্লেখ করতে হবে যে, উত্তরের সমস্ত উদাহরণে, উভয় প্রবাহ শেষ না হওয়া পর্যন্ত ভিন্নতাগুলি আসলে শুরু হবে না। উদাহরণস্বরূপ এটি পরীক্ষা করুন:

comm -23 <(seq 100 | sort) <(seq 10 20 && sleep 5 && seq 20 30 | sort)

যদি এটি কোনও সমস্যা হয় তবে আপনি এসডি (স্ট্রিম ডিফ) চেষ্টা করতে পারেন , যার commজন্য উপরের উদাহরণগুলির মতো বাছাই (যেমন করতে হবে) বা বিকল্প প্রতিস্থাপনের প্রয়োজন হয় না , এটি grep -f অসীম স্ট্রিমের চেয়ে দ্রুত এবং সমর্থন দেয় itude

আমার প্রস্তাবিত পরীক্ষার উদাহরণটি এভাবে লেখা হবে sd:

seq 100 | sd 'seq 10 20 && sleep 5 && seq 20 30'

তবে পার্থক্যটি এটি seq 100সঙ্গে সঙ্গে পৃথক করা হবে seq 10। মনে রাখবেন, স্ট্রিমগুলির মধ্যে একটি যদি একটি tail -fহয় তবে প্রক্রিয়া প্রতিস্থাপনের সাথে পার্থক্য করা যায় না।

এখানে একটি ব্লগপোস্ট আমি টার্মিনালে পৃথক প্রবাহ সম্পর্কে লিখেছিলাম, যা পরিচয় করিয়ে দেয় sd

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.