ড্যাশ মধ্যে প্রক্রিয়া সাবস্টিটিউশন অনুকরণ কিভাবে?


18

ইন bash, আমি প্রসেস সাবস্টিটিউশনটি ব্যবহার করতে পারি এবং কোনও প্রক্রিয়াটির আউটপুটকে এমন আচরণ করতে পারি যে এটি কোনও ডিস্কে সংরক্ষণ করা ফাইল file

$ echo <(ls)
/dev/fd/63

$ ls -lAhF <(ls)
lr-x------ 1 root root 64 Sep 17 12:55 /dev/fd/63 -> pipe:[1652825]

দুর্ভাগ্যক্রমে, প্রক্রিয়া সাবস্টিটিউশনটি সমর্থিত নয় dash

Process Substitutionড্যাশগুলিতে অনুকরণ করার সর্বোত্তম উপায় কী হবে ?

আমি আউটপুটটি কোথাও অস্থায়ী ফাইল হিসাবে সংরক্ষণ করতে চাই না ( /tmp/) এবং তারপরে এটি মুছতে হবে। বিকল্প উপায় আছে?


আপনি যা করার চেষ্টা করছেন তার উপর নির্ভর করে আপনি পাইপগুলি ব্যবহার করতে সক্ষম হতে পারেন।
এরিক রেনৌফ

সত্যিই, পোর্টেবিলিটিটি যদি এখানে আপনার প্রধান উদ্বেগ না হয় তবে কেবল bashআপনার ডিভাইসে ইনস্টল করা কি সহজ হবে না ?
আরকাদিউস দ্রবকিজিক

1
আপনি অনুগ্রহ বিজ্ঞপ্তিতে যে উদাহরণ সরবরাহ করেছেন তা এই লিঙ্কিত উত্তরের বিষয় হতে পারে । সেখানে প্রদর্শিত হিসাবে, গিলসের উত্তরের একটি সরল সংস্করণ (এর প্রাপ্যতা অনুমান করে /dev/fdএবং এর xz -cd <file>পরিবর্তে ব্যবহার করা cat <file> | xz -dযেতে পারে) xz -cd "$1" | { xz -cd "$2" | { diff /dev/fd/3 /dev/fd/4; } 3<&0; } 4<&0
ফ্রে-সান

1
@ ফ্রে-সান - এটি আসলে আমার প্রয়োজন ছিল। আপনি চাইলে এটি একটি উত্তর করতে পারেন। ধন্যবাদ।
মার্টিন ভেজিটার

উত্তর:


4

বর্তমান অনুগ্রহ বিজ্ঞপ্তিতে প্রশ্ন:

সাধারণ উদাহরণটি খুব জটিল। কেউ দয়া করে নীচের উদাহরণটি কীভাবে প্রয়োগ করবেন তা ব্যাখ্যা করতে পারেন?diff <(cat "$2" | xz -d) <(cat "$1" | xz -d)

এখানে একটি উত্তর আছে বলে মনে হচ্ছে ।

গিলসের উত্তরে যেমন দেখানো হয়েছে , সাধারণ ধারণাটি হ'ল "প্রযোজক" কমান্ডের আউটপুট নতুন ডিভাইস ফাইলগুলিতে 1 পাইপলাইনের বিভিন্ন পর্যায়ে প্রেরণ করে তাদের "ভোক্তা" কমান্ডগুলিতে উপলব্ধ করা হয়, যা সম্ভবত ফাইলের নামগুলি যুক্তি হিসাবে গ্রহণ করতে পারে ( ধরে নিচ্ছেন যে আপনার সিস্টেম আপনাকে ফাইল বর্ণনাকারীদের অ্যাক্সেস দেয় /dev/fd/X)।

আপনি যা সন্ধান করছেন তা অর্জনের সহজ উপায় সম্ভবত:

xz -cd file1.xz | { xz -cd file2.xz | diff /dev/fd/3 -; } 3<&0

( পঠনযোগ্যতার জন্য file1.xzজায়গায় "$1"এবং এর xz -cdপরিবর্তে cat ... | xz -dএকটি একক আদেশ যথেষ্ট) ব্যবহার করা হচ্ছে।

প্রথম "প্রযোজক" কমান্ডের আউটপুট, xz -cd file1.xzএকটি যৌগিক কমান্ডে পাইপ করা হয় ( {...}); তবে পরবর্তী কমান্ডের স্ট্যান্ডার্ড ইনপুট হিসাবে তাত্ক্ষণিকভাবে গ্রাস করার পরিবর্তে, এটি বিবরণী ফাইল করাতে নকল করা 3হয় এবং এইভাবে কমপઉન્ડ কমান্ডের অভ্যন্তরের সমস্ত কিছুর জন্য অ্যাক্সেসযোগ্য হয়ে যায় /dev/fd/3। দ্বিতীয় "প্রযোজক" কমান্ডের আউটপুট xz -cd file2.xz, যা তার স্ট্যান্ডার্ড ইনপুট বা ফাইল বর্ণনাকারীর কোনও কিছুই গ্রাস করে না 3, তারপরে "কনজিউমার" কমান্ডে পাইপ করা হয় diff, যা তার স্ট্যান্ডার্ড ইনপুট থেকে এবং পড়তে পারে /dev/fd/3

পাইপিং এবং ফাইল বর্ণনাকারীর সদৃশটি অনেকগুলি "প্রযোজক" কমান্ডের প্রয়োজন হিসাবে ডিভাইস ফাইল সরবরাহ করার জন্য যুক্ত করা যেতে পারে যেমন:

xz -cd file1.xz | { xz -cd file2.xz | { diff /dev/fd/3 /dev/fd/4; } 4<&0; } 3<&0

যদিও এটি আপনার নির্দিষ্ট প্রশ্নের প্রসঙ্গে অপ্রাসঙ্গিক হতে পারে, তবে এটি লক্ষণীয় যে:

  1. cmd1 <(cmd2) <(cmd3), cmd2 | { cmd3 | { cmd1 /dev/fd/3 /dev/fd/4; } 4<&0; } 3<&0এবং ( cmd2 | ( cmd3 | ( cmd1 /dev/fd/3 /dev/fd/4 ) 4<&0 ) 3<&0 )প্রাথমিক সম্পাদন পরিবেশে বিভিন্ন সম্ভাব্য প্রভাব রয়েছে।

  2. কি ঘটবে বিপরীত cmd1 <(cmd2) <(cmd3), cmd3এবং cmd1মধ্যে cmd2 | { cmd3 | { cmd1 /dev/fd/3 /dev/fd/4; } 4<&0; } 3<&0ব্যবহারকারীর কাছ থেকে কোনো ইনপুট পড়তে সক্ষম হবেন না। এর জন্য আরও ফাইল বর্ণনাকারীর প্রয়োজন হবে। উদাহরণস্বরূপ, মেলে

    diff <(echo foo) <(read var; echo "$var")
    

    আপনার মতো কিছু দরকার হবে

    { echo foo | { read var 0<&9; echo "$var" | diff /dev/fd/3 -; } 3<&0; } 9<&0
    

1 এর মধ্যে আরও কিছু ইউএন্ডএল , যেমন বোঝা / ডিভ এবং এর সাবডিয়ার এবং ফাইলগুলিতে পাওয়া যাবে


12

প্লাম্বিংটি ম্যানুয়ালি করে শেলটি ফণার নীচে কী করে তা পুনরুত্পাদন করতে পারে। আপনার সিস্টেমে যদি এন্ট্রি থাকে তবে আপনি ফাইল বিবরণী শিফলিং ব্যবহার করতে পারেন: আপনি অনুবাদ করতে পারেন/dev/fd/NNN

main_command <(produce_arg1) <(produce_arg2) >(consume_arg3) >(consume_arg4)

প্রতি

{ produce_arg1 |
  { produce_arg2 |
    { main_command /dev/fd5 /dev/fd6 /dev/fd3 /dev/fd4 </dev/fd/8 >/dev/fd/9; } 5<&0 3>&1 |
    consume_arg3; } 6<&0 4>&1; |
  consume_arg4; } 8<&0 9>&1

আমি একাধিক ইনপুট এবং ফলাফলগুলি চিত্রিত করার জন্য আরও জটিল উদাহরণ দেখিয়েছি। যদি আপনার স্ট্যান্ডার্ড ইনপুট থেকে পড়ার প্রয়োজন না হয় এবং আপনি প্রক্রিয়া প্রতিস্থাপন ব্যবহার করছেন তবে একমাত্র কারণ হ'ল কমান্ডটির একটি স্পষ্ট ফাইল নাম প্রয়োজন, আপনি কেবল ব্যবহার করতে পারেন /dev/stdin:

main_command <(produce_arg1)
produce_arg1 | main_command /dev/stdin

ছাড়া , আপনার একটি নামযুক্ত পাইপ ব্যবহার করা দরকার । একটি নামক পাইপ একটি ডিরেক্টরি এন্ট্রি, সুতরাং আপনার কোথাও একটি অস্থায়ী ফাইল তৈরি করা দরকার, তবে সেই ফাইলটি কেবল একটি নাম, এতে কোনও ডেটা থাকে না।/dev/fd/NNN

tmp=$(mktemp -d)
mkfifo "$tmp/f1" "$tmp/f2" "$tmp/f3" "$tmp/f4"
produce_arg1 >"$tmp/f1" &
produce_arg2 >"$tmp/f2" &
consume_arg3 <"$tmp/f3" &
consume_arg4 <"$tmp/f4" &
main_command "$tmp/f1" "$tmp/f2" "$tmp/f3" "$tmp/f4"
rm -r "$tmp"

2
</dev/fd/8 >/dev/fd/9<&8 >&9লিনাক্সের সমতুল্য নয় এবং এড়ানো উচিত।
স্টাফেন শেজেলাস

@ গিলস - জটিল উদাহরণটি দেখে আমি বিভ্রান্ত। আপনি কি দয়া করে কিভাবে অনুকরণ দেন যায়নি: diff <(cat "$2" | xz -d) <(cat "$1" | xz -d)?
মার্টিন ভেজিটার

3

কেউ দয়া করে নীচের উদাহরণটি কীভাবে প্রয়োগ করবেন তা ব্যাখ্যা করতে পারেন?
diff <(cat "$2" | xz -d) <(cat "$1" | xz -d)

আমি মনে করি নামযুক্ত পাইপগুলি পুনঃনির্দেশের চেয়ে কুঁচকানো সহজ, তাই সহজ ভাষায়:

mkfifo p1 p2               # create pipes
cat "$2" | xz -d > p1 &    # start the commands in the background
cat "$1" | xz -d > p2 &    #    with output to the pipes
diff p1 p2                 # run 'diff', reading from the pipes
rm p1 p2                   # remove them at the end

p1এবং p2অস্থায়ী নামক পাইপ, তাদের নামকরণ করা যেতে পারে।

পাইপগুলিতে তৈরি করা আরও স্মার্ট হবে /tmp, উদাহরণস্বরূপ গিলেস এর উত্তর শো হিসাবে একটি ডিরেক্টরিতে , এবং মনে রাখবেন যে আপনার catএখানে দরকার নেই তাই:

tmpdir=$(mktemp -d)
mkfifo "$tmpdir/p1" "$tmpdir/p2"
xz -d < "$2" > "$tmpdir/p1" &
xz -d < "$1" > "$tmpdir/p2" &
diff "$tmpdir/p1" "$tmpdir/p2"
rm -r "$tmpdir"

( mktempসম্ভবত আপনি "সুন্দর" ফাইলের নাম তৈরি করার সম্ভাবনা রয়েছে বলেই সম্ভবত উদ্ধৃতিগুলি ছাড়াই পলায়ন করতে পারেন))

পাইপের সমাধানটিতে সতর্কতা রয়েছে যে যদি diffসমস্ত ইনপুট পড়ার আগে প্রধান কমান্ড ( ) মারা যায় তবে পটভূমি প্রক্রিয়াগুলি ঝুলন্ত অবস্থায় ফেলে রাখা যেতে পারে।


0

কি সম্পর্কে:

cat "$2" | xz -d | diff /dev/sdtin /dev/stderr 2<<EOT
`cat "$1" | xz -d`
EOT
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.