আমি কীভাবে একাধিক আদেশে stdout প্রেরণ করতে পারি?


186

কিছু কমান্ড যা ফিল্টার বা আইন ইনপুটের আছে, এবং তারপর আউটপুট বরাবর এটা পাস, আমি সাধারণত মনে করি stdout- কিন্তু কিছু কমান্ড শুধু নিতে হবে stdinএবং তারা এটা দিয়ে কি করবেন, এবং আউটপুট কিছুই নেই।

আমি ওএস এক্সের সাথে সর্বাধিক পরিচিত এবং তাই দু'জন তাৎক্ষণিকভাবে মাথায় আসে pbcopyএবং pbpasteযা সিস্টেম ক্লিপবোর্ড অ্যাক্সেসের মাধ্যম।

যাইহোক, আমি জানি যে আমি যদি স্টডআউট নিতে এবং আউটপুট উভয় stdoutএবং একটি ফাইল যেতে স্পিট করতে চান তবে আমি teeকমান্ডটি ব্যবহার করতে পারি । এবং আমি কিছুটা সম্পর্কে জানি xargs, তবে আমি মনে করি না এটি আমি যা খুঁজছি।

আমি জানতে চাই যে কীভাবে আমি stdoutদুটি (বা আরও) কমান্ডের মধ্যে যেতে পারি split উদাহরণ স্বরূপ:

cat file.txt | stdout-split -c1 pbcopy -c2 grep -i errors

এর চেয়ে সম্ভবত আরও ভাল উদাহরণ থাকতে পারে, তবে আমি কীভাবে স্ট্যান্ডআউটকে কোনও কমান্ডের রিলে না পাঠাতে পারি এবং stdout"নিঃশব্দ" থেকে রক্ষা করার সময়ে আমি কীভাবে catফাইল করব এবং সে সম্পর্কে জিজ্ঞাসা করছি না তা জানতে আগ্রহী grepএটির একটি অংশ এবং এটি ক্লিপবোর্ডে অনুলিপি করুন - নির্দিষ্ট কমান্ডগুলি গুরুত্বপূর্ণ নয় important

এছাড়াও - আমি এটি কোনও ফাইলে কীভাবে প্রেরণ করব তা জিজ্ঞাসা করছি না এবং stdout- এটি একটি "নকল" প্রশ্ন হতে পারে (দুঃখিত) তবে আমি কিছু সন্ধান করেছি এবং কেবল একই ধরণের সন্ধান পেয়েছি যা স্টাডআউট এবং একটি ফাইলের মধ্যে কীভাবে বিভক্ত হবে সে সম্পর্কে জিজ্ঞাসা করছে - এবং এই প্রশ্নের উত্তরগুলি দেখে মনে হয়েছিল teeযা আমার পক্ষে কার্যকর হবে বলে আমি মনে করি না।

অবশেষে, আপনি জিজ্ঞাসা করতে পারেন "পাইপ চেইনে কেবল পবকপিই শেষ জিনিসটি তৈরি করেন না কেন?" এবং আমার প্রতিক্রিয়া 1) আমি যদি এটি ব্যবহার করতে এবং কনসোলে আউটপুটটি দেখতে চাই তবে কী হবে? 2) যদি আমি দুটি কমান্ড ব্যবহার করতে চাই যা stdoutইনপুট প্রক্রিয়া করার পরে আউটপুট হয় না ?

ওহ, এবং আরও একটি জিনিস - আমি বুঝতে পারি যে আমি ব্যবহার করতে পারি teeএবং একটি নামযুক্ত পাইপ ( mkfifo) তবে আমি পূর্বের সেটআপ ব্যতীত কোনওভাবে ইনলাইনটি সম্পন্ন করার উপায়টি আশা করছিলাম :)


উত্তর:


239

আপনি এর teeজন্য বিকল্প ব্যবহার করতে এবং প্রক্রিয়া করতে পারেন :

cat file.txt | tee >(pbcopy) | grep errors

এই সব আউটপুট পাঠাব cat file.txtকরতে pbcopy, এবং আপনি শুধুমাত্র ফল পাবেন grepআপনার কনসোলে।

আপনি teeঅংশে একাধিক প্রক্রিয়া রাখতে পারেন :

cat file.txt | tee >(pbcopy) >(do_stuff) >(do_more_stuff) | grep errors

21
এর সাথে উদ্বেগ নয় pbcopy, তবে সাধারণভাবে উল্লেখ করার মতো: প্রক্রিয়াটির বিকল্প আউটপুট যাই হোক না কেন মূল পাইনের পরে পরবর্তী পাইপ বিভাগ দ্বারাও দেখা যায়; উদাহরণস্বরূপ: seq 3 | tee >(cat -n) | cat -e( cat -nইনপুট লাইনগুলিকে সংখ্যায়িত করে, cat -eনতুন লাইনগুলি চিহ্নিত করে $; আপনি দেখতে পাবেন যে cat -eএটি মূল ইনপুট (প্রথম) এবং (তারপরে) থেকে আউটপুট উভয় ক্ষেত্রেই প্রয়োগ করা হয়েছে cat -n)। একাধিক প্রক্রিয়া বিকল্পগুলি থেকে আউটপুট অ-নিরস্তকরণ ক্রমে উপস্থিত হবে।
mklement0

49
>(শুধুমাত্র কাজ করে bash। আপনি যদি উদাহরণস্বরূপ ব্যবহার করে চেষ্টা করেন তবে shএটি কাজ করবে না। এই নোটিশ করা গুরুত্বপূর্ণ।
এএলভিজ

10
@AAlvz: গুড পয়েন্ট: প্রক্রিয়া প্রতিকল্পন হয় না একটি POSIX বৈশিষ্ট্য; dash, যা shউবুন্টুর মতো কাজ করে, এটি সমর্থন করে না, এমনকি বাশ নিজেই যখন বৈশিষ্ট্যটি নিষ্ক্রিয় করে তখন shবা কখন set -o posixকার্যকর হয়। তবে এটি কেবল বাশ নয় যা প্রক্রিয়া বিকল্পগুলি সমর্থন করে: kshএবং সেগুলিও zshসমর্থন করে (অন্যদের সম্পর্কে নিশ্চিত নয়)।
mklement0

2
@ mklement0 যা সত্য বলে মনে হচ্ছে না। জেডশিতে (উবুন্টু 14.04) আপনার লাইন প্রিন্ট করে: 1 1 2 2 3 3 1 1 $ 2 $ 3 $ যা দুঃখজনক, কারণ আমি সত্যই চেয়েছিলাম যে আপনি যা বলেছেন ঠিক তেমন কার্যকারিতা হোক।
আকতাউ

2
@ আকতাউ: প্রকৃতপক্ষে, আমার নমুনা কমান্ডটি কেবল বর্ণিত হিসাবে কাজ করে bashএবং ksh- zshদৃশ্যত পাইপলাইনের মাধ্যমে আউটপুট প্রক্রিয়া বিকল্পগুলি থেকে আউটপুট প্রেরণ করে না (তর্কাতীতভাবে, এটি পছন্দনীয় , কারণ এটি পরবর্তী পাইপলাইন বিভাগে প্রেরিত যা দূষিত করে না - যদিও এটি এখনও মুদ্রণ করে )। ইন সব আউটপুট ক্রম আন্দাজের হবে না, একটি পদ্ধতিতে যে শুধুমাত্র কখনোসখনো বা বড় সঙ্গে পৃষ্ঠ পারে - উল্লিখিত শাঁস যদিও, সাধারণভাবে একটি একক পাইপলাইন যা নিয়মিত stdout- এ আউটপুট এবং প্রক্রিয়া বদল থেকে আউটপুট মিশ্র আছে করার জন্য একটি ভাল ধারণা আউটপুট ডেটা সেট।
mklement0

124

আপনি একাধিক ফাইলের নাম উল্লেখ করতে পারেন teeএবং মানক আউটপুট একটি কমান্ডে পাইপ করা যায়। একাধিক কমান্ডে আউটপুট প্রেরণ করতে, আপনাকে একাধিক পাইপ তৈরি করতে হবে এবং তাদের প্রতিটিকে একটি আউটপুট হিসাবে নির্দিষ্ট করতে হবে tee। এই কাজ করার বিভিন্ন উপায় আছে।

প্রক্রিয়া প্রতিস্থাপন

যদি আপনার শেলটি ksh93, ব্যাশ বা zsh হয় তবে আপনি প্রক্রিয়া বিকল্প ব্যবহার করতে পারেন। এটি কোনও কমান্ডের কাছে পাইপ পাস করার একটি উপায় যা কোনও ফাইল নাম প্রত্যাশা করে। শেলটি পাইপ তৈরি করে এবং /dev/fd/3কমান্ডের মতো একটি ফাইলের নাম পাস করে। নম্বরটি হ'ল ফাইল বর্ণনাকারী যা পাইপটি সংযুক্ত রয়েছে। কিছু ইউনিক্স রূপগুলি সমর্থন করে না /dev/fd; এর উপর, পরিবর্তে একটি নামযুক্ত পাইপ ব্যবহার করা হয় (নীচে দেখুন)।

tee >(command1) >(command2) | command3

ফাইল বর্ণনাকারী

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

{ { { tee /dev/fd/3 /dev/fd/4 | command1 >&9;
    } 3>&1 | command2 >&9;
  } 4>&1 | command3 >&9;
} 9>&1

নামকরণ পাইপ

সর্বাধিক প্রাথমিক এবং বহনযোগ্য পদ্ধতি হ'ল নামযুক্ত পাইপগুলি ব্যবহার করা । খারাপ দিকটি হ'ল আপনাকে একটি লিখনযোগ্য ডিরেক্টরি খুঁজে বের করতে হবে, পাইপগুলি তৈরি করতে হবে এবং পরে পরিষ্কার করতে হবে।

tmp_dir=$(mktemp -d)
mkfifo "$tmp_dir/f1" "$tmp_dir/f2"
command1 <"$tmp_dir/f1" & pid1=$!
command2 <"$tmp_dir/f2" & pid2=$!
tee "$tmp_dir/f1" "$tmp_dir/f2" | command3
rm -rf "$tmp_dir"
wait $pid1 $pid2

10
যারা ব্যাশ বা নির্দিষ্ট কোনও ksh এর উপর নির্ভর করতে চান না তাদের জন্য দুটি বিকল্প সংস্করণ সরবরাহ করার জন্য আপনাকে অনেক ধন্যবাদ।
trr

tee "$tmp_dir/f1" "$tmp_dir/f2" | command3command3 | tee "$tmp_dir/f1" "$tmp_dir/f2"আপনি অবশ্যই command3পাইপ স্টাড্ট চাই tee, না? আমি আপনার সংস্করণটির অধীনে পরীক্ষা করেছি dashএবং teeঅনির্দিষ্টকালের জন্য ইনপুটটির অপেক্ষায় অবরুদ্ধ হয়েছি , তবে আদেশটি স্যুইচিংয়ের ফলে প্রত্যাশিত ফলাফল প্রকাশিত হয়েছে।
অ্যাড্রিয়ান গন্টার

1
@ AdrianGünter নং তিনটি উদাহরণ স্ট্যান্ডার্ড ইনপুট থেকে ডেটা পড়তে এবং প্রতিটি পাঠাতে command, command2এবং command3
গিলস

@ গিলস আমি দেখতে পেয়েছি, আমি অভিপ্রায়টির ভুল ব্যাখ্যা দিয়েছি এবং স্নিপেটটি ভুলভাবে ব্যবহার করার চেষ্টা করেছি। স্পষ্টতার জন্য ধন্যবাদ!
অ্যাড্রিয়ান গন্টার

যদি ব্যবহৃত শেলটিতে আপনার কোনও নিয়ন্ত্রণ না থাকে তবে আপনি স্পষ্টভাবে ব্যাশ ব্যবহার করতে পারেন, আপনি এটি করতে পারেন <command> | bash -c 'tee >(command1) >(command2) | command3'। এটি আমার ক্ষেত্রে সহায়তা করেছে।
gc5

16

কেবল প্রক্রিয়া বিকল্পের সাথে খেলুন।

mycommand_exec |tee >(grep ook > ook.txt) >(grep eek > eek.txt)

grepদুটি বাইনারি যা mycommand_execতাদের প্রক্রিয়া নির্দিষ্ট ইনপুট হিসাবে একই আউটপুট থাকে ।


16

আপনি যদি ব্যবহার করে থাকেন zshতবে আপনি MULTIOSবৈশিষ্ট্যের শক্তির সুবিধা নিতে পারেন , অর্থাত্ teeকমান্ডটি পুরোপুরি মুক্তি দিন :

uname >file1 >file2

কেবল unameদুটি পৃথক ফাইলের আউটপুট লিখব : file1এবং file2, এর সমতুল্যuname | tee file1 >file2

একইভাবে স্ট্যান্ডার্ড ইনপুটগুলির পুনঃনির্দেশ

wc -l <file1 <file2

এর সমতুল্য cat file1 file2 | wc -l(দয়া করে মনে রাখবেন যে এটি প্রতিটি হিসাবে wc -l file1 file2পৃথক পৃথকভাবে লাইন সংখ্যা গণনা করে) এটি একই নয় ।

অবশ্যই আপনি MULTIOSআউটপুট ফাইলগুলিতে নয় অন্য প্রক্রিয়াগুলিতে প্রক্রিয়াকরণের বিকল্প ব্যবহার করে পুনঃনির্দেশ করতেও ব্যবহার করতে পারেন , উদাহরণস্বরূপ:

echo abc > >(grep -o a) > >(tr b x) > >(sed 's/c/y/')

3
জানা ভাল. MULTIOSএটি একটি বিকল্প যা ডিফল্টরূপে চালু থাকে (এবং এটি দিয়ে বন্ধ করা যেতে পারে unsetopt MULTIOS)।
mklement0

6

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

নিম্নলিখিত স্ক্রিপ্ট, উদাহরণস্বরূপ, এটি করতে পারে:

#!/bin/sh

temp=$( mktemp )
cat /dev/stdin > "$temp"

for arg
do
    eval "$arg" < "$temp"
done
rm "$temp"

শেল /bin/shহিসাবে উবুন্টু 16.04 এ পরীক্ষা করুন dash:

$ cat /etc/passwd | ./multiple_pipes.sh  'wc -l'  'grep "root"'                                                          
48
root:x:0:0:root:/root:/bin/bash

5

STDOUTকোনও ভেরিয়েবলের কমান্ডটি ক্যাপচার করুন এবং এটি আপনার পছন্দমতো পুনরায় ব্যবহার করুন:

commandoutput="$(command-to-run)"
echo "$commandoutput" | grep -i errors
echo "$commandoutput" | pbcopy

যদি STDERRআপনারও ক্যাপচার দরকার হয় 2>&1তবে কমান্ডের শেষে ব্যবহার করুন , এর মতো:

commandoutput="$(command-to-run 2>&1)"

3
ভেরিয়েবলগুলি কোথায় সংরক্ষণ করা হয়? আপনি যদি একটি বড় ফাইল বা এই ধরণের কিছু নিয়ে কাজ করে থাকেন তবে এই হোগটি কি খুব বেশি স্মৃতি রাখে না? ভেরিয়েবলগুলি কি আকারে সীমিত?
সিডব্লিউ

1
কী যদি $ কমান্ডআউটপুট বিশাল হয় ?, পাইপ ব্যবহার এবং বিকল্প প্রতিস্থাপন করা আরও ভাল।
নিখিল মুলি

4
স্পষ্টতই এই সমাধানটি তখনই সম্ভব যখন আপনি জানেন যে আউটপুটটির আকার সহজেই মেমরির সাথে খাপ খায় এবং আপনার পরবর্তী কমান্ডগুলি চালানোর আগে আপনি পুরো আউটপুটটি বাফারিং দিয়ে ঠিক আছেন OK পাইপগুলি স্বেচ্ছাসেবী দৈর্ঘ্যের ডেটা মঞ্জুরি দিয়ে এবং উত্পন্ন হওয়ার সাথে সাথে রিসিভারে রিয়েল টাইমে স্ট্রিমিং করে এই দুটি সমস্যা সমাধান করে।
trr

2
এটি যদি আপনার ছোট আউটপুট থাকে তবে এটি একটি ভাল সমাধান এবং আপনি জানেন যে আউটপুটটি বাইনারি নয় পাঠ্য হবে। (শেল ভেরিয়েবলগুলি প্রায়শই বাইনারি নিরাপদ হয় না)
রুসেন্ট ৮৮

1
বাইনারি ডেটা নিয়ে কাজ করতে আমি এটি পেতে পারি না। আমি মনে করি এটি প্রতিধ্বনি সহ এমন কিছু যা নাল বাইট বা অন্য কিছু ননক্র্যাক্টরের ডেটা ব্যাখ্যা করার চেষ্টা করছে।
রল্ফ

1

এটি কার্যকর হতে পারে: http://www.spinellis.gr/sw/dgsh/ (নির্দেশিত গ্রাফ শেল) "মাল্টিপাইপ" কমান্ডের জন্য একটি সহজ সিনট্যাক্সকে সমর্থনকারী ব্যাশ প্রতিস্থাপনের মতো মনে হয়।


0

এখানে একটি দ্রুত এবং নোংরা আংশিক সমাধান, যেকোন শেল সহ সামঞ্জস্যপূর্ণ busybox

এটি যত সঙ্কুচিত সমস্যাটি সমাধান করবে তা হ'ল: stdoutএকটি কনসোলে সম্পূর্ণ মুদ্রণ করুন এবং অস্থায়ী ফাইল বা নামযুক্ত পাইপ ছাড়াই অন্যটিতে এটি ফিল্টার করুন।

  • একই হোস্টে অন্য সেশন শুরু করুন। এর টিটিওয়াই নামটি জানার জন্য টাইপ করুন tty। ধরে নেওয়া যাক /dev/pty/2
  • প্রথম সেশনে, চালান the_program | tee /dev/pty/2 | grep ImportantLog:

আপনি একটি সম্পূর্ণ লগ এবং একটি ফিল্টার পেয়েছেন।

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