বাশের "ম্যাপফাইলে" পাইপ দেওয়া যায় না ... তবে কেন?


13

আমি কেবলমাত্র একটি নির্দিষ্ট ডিরেক্টরিতে থাকা সমস্ত ফাইলকে ব্যাশ অ্যারেতে নিয়ে যেতে চাই (ধরে নিই যে ফাইলগুলির কোনওটির নামে নতুন লাইন নেই):

তাই:

myarr=()
find . -maxdepth 1  -name "mysqldump*" | mapfile -t myarr; echo "${myarr[@]}"

খালি ফলাফল!

যদি আমি কোনও ফাইল, অস্থায়ী বা অন্য কোনওভাবে ব্যবহারের রাউন্ডআউট পদ্ধতি করি:

myarr=()
find . -maxdepth 1  -name "mysqldump*" > X
mapfile -t myarray < X
echo "${myarray[@]}"

ফলাফল!

তবে mapfileপাইপ থেকে কেন সঠিকভাবে পড়ছেন না?



চারদিকে দুর্দান্ত উত্তর, সবাইকে ধন্যবাদ। আকর্ষণীয় কীভাবে পাইপলাইনের কার্যকরকরণ কৌশল (প্রতিটি অংশ একটি স্পেরেট প্রক্রিয়াতে চলছে) "উপরের দিকে" ফাঁস করে এবং কোডটির আপাত অর্থটি সংশোধন করে, মূলত নীরবে পাইপটিতে উপস্থিত প্রতিটি ভেরিয়েবলের সামনে "স্থানীয়" রাখে। এমন একটি ভাষায় যা অন্যান্য প্রোগ্রামগুলির জন্য ক্রেজি আঠার বাইরে অন্য কিছু, আশাবাদী এটি বাগ be
ডেভিড টনহোফার

2
আপনি শেলচেককে কোডটি দিলে , আপনি সতর্কতা পেয়ে যাবেন : এসসি 2030 : " ভের সংশোধন স্থানীয় (পাইপলাইনের ফলে সাবসেল করার জন্য )" এবং এসসি 2031 : " ভের একটি সাবশেলে পরিবর্তন করা হয়েছিল। সেই পরিবর্তনটি হারিয়ে যেতে পারে" " । চমৎকার।
ডেভিড টোনহোফার

কেন findএবং mapfileএখানে এবং কেন না শুধুমাত্র সহজ ব্যবহার myarr=(mysqldump*)? এটি এমনকি ফাঁকা স্থান এবং নতুন লাইনের ফাইলনামগুলির সাথেও কাজ করবে।
ব্ল্যাকজ্যাক

1
সবেমাত্র লক্ষ্য করা গেছে যে কোনও ফাইল ম্যাচ না করায় অ্যারে দিয়ে শেষ না হওয়ার জন্য একটিকে nullglob( shopt -s nullglob) চালু myarr=(mysqldump*)করতে হবে ('mysqldump*')
ডেভিড টনহোফার

উত্তর:


25

থেকে man 1 bash:

পাইপলাইনের প্রতিটি কমান্ড পৃথক প্রক্রিয়া হিসাবে (যেমন, একটি সাবসিলে) চালিত হয়।

এই জাতীয় সাব-শেলগুলি মূল শেল থেকে ভেরিয়েবলের উত্তরাধিকারী তবে তারা স্বতন্ত্র। এর অর্থ mapfileআপনার আসল কমান্ডটি এর নিজস্ব কাজ করে myarr। তারপরে echo(পাইপের বাইরে থাকা) খালি প্রিন্ট করে myarr(যা মূল শেল এর myarr)।

এই আদেশটি ভিন্নভাবে কাজ করে:

find . -maxdepth 1 -name "mysqldump*" | { mapfile -t myarr; echo "${myarr[@]}"; }

এই ক্ষেত্রে mapfileএবং echoএকই myarr(যা মূল শেল এর নয় myarr) চালিয়ে যান ।

প্রধান শেলটি পরিবর্তন করতে myarrআপনাকে mapfileমূল শেলটিতে ঠিক চালাতে হবে । উদাহরণ:

myarr=()
mapfile -t myarr < <(find . -maxdepth 1 -name "mysqldump*")
echo "${myarr[@]}"

অ্যাটিয়ের প্রতিক্রিয়া অনুসারে প্রদত্ত "প্রক্রিয়া বিকল্প" -এর লিঙ্কটি যুক্ত হয়েছে, যদি কোনও দর্শকের কাছে টিএল; ডিআর মুহুর্ত থাকে।
ডেভিড টনহোফার

11

বাশ একটি সাব-শেল এনভায়রনমেন্টে পাইপলাইনের কমান্ড চালায়, সুতরাং এর মধ্যে যে কোনও পরিবর্তনশীল অ্যাসাইনমেন্ট ইত্যাদি থাকে তা বাকি শেলের কাছে দৃশ্যমান হয় না।

ড্যাশ (দেবিয়ান /bin/sh) পাশাপাশি shব্যস্তবক্সগুলি একইরকম, যখন zsh এবং ksh মূল শেলের শেষ অংশটি চালায়। বাশ-এ, আপনি এটি করতে ব্যবহার করতে পারেন shopt -s lastpipe, তবে এটি শুধুমাত্র কাজ নিয়ন্ত্রণ যখন অক্ষম থাকে তখন ডিফল্টরূপে ইন্টারেক্টিভ শেলগুলিতে নয় lls

তাই:

$ bash -c 'x=a; echo b | read x; echo $x'
a
$ bash -c 'shopt -s lastpipe; x=a; echo b | read x; echo $x'
b

( readএবং mapfileএকই সমস্যা আছে।)

বিকল্পভাবে (এবং অ্যাটি দ্বারা উল্লিখিত হিসাবে ), প্রক্রিয়া বিকল্প ব্যবহার করুন , যা একটি সাধারণ পাইপের মতো কাজ করে এবং ব্যাশ, কেএসএস এবং জেডএসে সমর্থিত।

$ bash -c 'x=a; read x < <(echo b); echo $x'
b

কোনও পাইপলাইনের অংশগুলি সাবশেলে চালিত হয় বা না পজিক্স এটিকে অনির্ধারিতভাবে ছেড়ে দেয়, সুতরাং এটি সত্যই বলা যায় না যে কোনও শাঁসই এতে "ভুল" হবে।


2
আপনি যদি বাশের কাজের নিয়ন্ত্রণ অক্ষম করেন তবে আপনি ইন্টারেক্টিভ শেলটিতে লাস্টপাইপটিও ব্যবহার করতে পারেন:set +m; shopt -s lastpipe; x=a; echo b | read x; echo $x; set -m
সাইরাস

@ সাইরাস, ঠিক আছে, আমি বিশদটি ভুলে
গিয়েছি

9

কামিল যেমন উল্লেখ করেছেন, পাইপলাইনের প্রতিটি উপাদান একটি পৃথক প্রক্রিয়া।

আপনার বর্তমান দোভাষীর কাছে অনুরোধ রইল, পরবর্তীটিতে অ্যাক্সেসের অনুমতি দিয়ে আপনি একটি পৃথক প্রক্রিয়া চালানোর জন্য নিম্নলিখিত প্রক্রিয়া বিকল্পটি ব্যবহার করতে পারেন :findmapfilemyarr

myarr=()
mapfile -t myarr < <( find . -maxdepth 1  -name "mysqldump*" )
echo "${myarr[@]}"

b < <( a )a | bপাইপলাইনটি কীভাবে তারযুক্ত হয় তার ক্ষেত্রে একইভাবে কাজ করবে - পার্থক্যটি এটি b" এখানে " কার্যকর করা হয় ।

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