সাব-শেল ব্যবহার না করে শেল কমান্ডের বিকল্প প্রয়োগ করা সম্ভব?


11

আমার এমন একটি দৃশ্য আছে যা সাব-শেল ব্যবহার না করে কমান্ড প্রতিস্থাপনের জন্য কল করে। আমার এইরকম একটি নির্মাণ রয়েছে:

pushd $(mktemp -d)

এখন আমি প্রস্থান করতে এবং একযোগে অস্থায়ী ডিরেক্টরিটি সরাতে চাই:

rmdir $(popd)

তবে এটি কাজ করে না কারণ popdপপড ডিরেক্টরিটি ফেরত দেয় না (এটি নতুন, এখনকার বর্তমান, ডিরেক্টরিটি ফেরত দেয়) এবং কারণ এটি একটি সাবসিলে সঞ্চালিত হয়েছে।

কিছুটা এইরকম

dirs -l -1 ; popd &> /dev/null

পপড ডিরেক্টরিটি ফিরিয়ে দেবে তবে এটি এর মতো ব্যবহার করা যাবে না:

rmdir $(dirs -l -1 ; popd &> /dev/null)

কারণ popdইচ্ছেটি কেবল সাব-শেলকেই প্রভাবিত করবে। যার জন্য বলা হয় তা করার ক্ষমতা:

rmdir { dirs -l -1 ; popd &> /dev/null; }

তবে এটি অবৈধ বাক্য গঠন। এই প্রভাব অর্জন করা সম্ভব?

(দ্রষ্টব্য: আমি জানি আমি একটি পরিবর্তনশীল মধ্যে অস্থায়ী ডিরেক্টরি সংরক্ষণ করতে পারি; আমি এটি করার প্রয়োজন এড়াতে এবং প্রক্রিয়াতে নতুন কিছু শিখতে চেষ্টা করছিলাম!)


1
আমি ডিরেক্টরিটি একটি ভেরিয়েবলে সংরক্ষণ করব; এই পদ্ধতিতে, কোনও trapহ্যান্ডলার ডিরেক্টরিটি ক্লিনআপ করতে পারে যদি কোনও সিগন্যাল দ্বারা প্রক্রিয়াটি পোজ করা উচিত।
14-18 এ

উত্তর না হয়
h0tw1r3

এটি দেখতে যেমন fishকমান্ড প্রতিস্থাপনের সমতুল্য (), বাইরের শেলের ফোল্ডারটি পরিবর্তন করে। এটি সাধারণত বিরক্তিকর, তবে এর মতো ক্ষেত্রে এটি দরকারী, আমি নিশ্চিত।
ট্রাইসিস

উত্তর:


10

আপনার প্রশ্নের শিরোনামের পছন্দটি কিছুটা বিভ্রান্তিকর।

pushd/ popd, একটি cshবৈশিষ্ট্য দ্বারা অনুলিপি করা হয়েছে bashএবং zsh, মনে রাখা ডিরেক্টরিগুলির স্ট্যাক পরিচালনা করার একটি উপায়।

pushd /some/dir

বর্তমান ওয়ার্কিং ডিরেক্টরিটি একটি স্ট্যাকের দিকে ঠেলে দেয় এবং তারপরে বর্তমান ওয়ার্কিং ডিরেক্টরিটি পরিবর্তন করে (এবং তারপরে /some/dirসেই স্ট্যাকের সামগ্রী (স্পেস-বিভাজিত) দ্বারা প্রিন্ট করা হয়।

popd

স্ট্যাকের সামগ্রী মুদ্রণ করে (আবার স্থান পৃথক করে) এবং তারপরে স্ট্যাকের শীর্ষ উপাদানগুলিতে পরিবর্তিত হয় এবং স্ট্যাক থেকে পপ করে।

(এছাড়াও সাবধান যে কিছু ডিরেক্টরি তাদের ~/xবা ~user/xস্বরলিপি দিয়ে সেখানে প্রতিনিধিত্ব করা হবে )।

সুতরাং যদি বর্তমানে স্ট্যাকটি রয়েছে /aএবং /b, বর্তমান ডিরেক্টরিটি রয়েছে /hereএবং আপনি চলছে:

 pushd /tmp/whatever
 popd

pushdমুদ্রণ /tmp/whatever /here /a /bএবং popdআউটপুট হবে /here /a /b, না /tmp/whatever। এটি কমান্ড সাবস্টিটিউশন বা না ব্যবহারের ক্ষেত্রে স্বাধীন। popdপূর্ববর্তী ডিরেক্টরিটির পাথ পেতে ব্যবহার করা যায় না এবং সাধারণভাবে এর আউটপুটটি প্রক্রিয়াজাত করা যায় না ( ডিরেক্টরি স্ট্যাকের উপাদানগুলির অ্যাক্সেসের জন্য কিছু শেলের শাঁস $dirstackবা $DIRSTACKঅ্যারে দেখুন )

আপনি চান:

pushd "$(mktemp -d)" &&
popd &&
rmdir "$OLDPWD"

অথবা

cd "$(mktemp -d)" &&
cd - &&
rmdir "$OLDPWD"

যদিও, আমি ব্যবহার করব:

tmpdir=$(mktemp -d) || exit
(
  cd "$tmpdir" || exit # in a subshell 
  # do what you have to do in that tmpdir
)
rmdir "$tmpdir"

যাই হোক pushd "$(mktemp -d)"না কেন , pushdএকটি সাব-শেল চলবে না। যদি এটি করা থাকে তবে এটি কার্যকারী ডিরেক্টরিটি পরিবর্তন করতে পারে না। এটি mktempএকটি সাব-শেলের মধ্যে চলে। যেহেতু এটি একটি পৃথক কমান্ড, তাই এটি একটি পৃথক প্রক্রিয়াতে চালিত হতে হবে। এটি একটি পাইপে তার আউটপুট লিখেছে, এবং শেল প্রক্রিয়াটি পাইপের অন্য প্রান্তে পড়ে reads

কমান্ডটি অন্তর্নির্মিত হওয়ার সাথে সাথে ksh93 পৃথক প্রক্রিয়াটি এড়াতে পারে, তবে সেখানে এখনও এটি একটি সাবশেল (একটি ভিন্ন কার্যকরী পরিবেশ) যা এই সময়টি সাধারণত কাঁটাচামচ দ্বারা সরবরাহ করা পৃথক পরিবেশের উপর নির্ভর করার পরিবর্তে অনুকরণ করা হয়। উদাহরণস্বরূপ, মধ্যে ksh93, a=0; echo "$(a=1; echo test)"; echo "$a"কোনও কাঁটাচামচ জড়িত নয়, তবে এখনও ফলাফল echo "$a"আউটপুট করে 0

এখানে, আপনি যদি আউটপুট সঞ্চয় করতে চান mktempএকটি পরিবর্তনশীল একই সময় হিসাবে আপনি এটি পাস এ pushdসঙ্গে zsh, আপনি কি পারে:

pushd ${tmpdir::="$(mktemp -d)"}

বোর্নের মতো শেলগুলির সাথে:

unset tmpdir
pushd "${tmpdir=$(mktemp -d)}"

অথবা $(mktemp -d)বেশ কয়েকটি বারের আউটপুটটি স্পষ্টভাবে কোনও ভেরিয়েবলে সংরক্ষণ না করে ব্যবহার করার জন্য, আপনি zshবেনামে ফাংশন ব্যবহার করতে পারেন :

(){pushd ${1?} && cd - && rmdir $1} "$(mktemp -d)"

আমি বুঝতে পেরেছি pushdএবং popdআপনার বর্ণনা অনুসারে কাজ করার জন্য এবং তারা কমান্ড প্রতিস্থাপনের চেয়ে স্বাধীন - সেখানে কোনও বিভ্রান্তি নেই! তবে, আপনি প্রকাশ করে নিজের সমস্যার উত্তর দিয়েছিলেন $OLDPWD। আমি করতে পারি popd; rmdir $OLDPWD। এটাই আমার সমস্যার উত্তর - অন্য সমস্ত কিছুই কেবল আমি যা ভেবেছিলাম তা নিশ্চিত করে। কমান্ড প্রতিস্থাপন এটি সমাধানের উপায় বলে মনে হচ্ছে তবে এটি সাবসেলের কারণে নয় এবং আপনি সাবস্কেল ব্যতীত কমান্ড প্রতিস্থাপন করতে পারবেন না, সুতরাং ওলডিপিডাব্লুডি প্রকাশ করার জন্য ধন্যবাদ - আমার ঠিক এটিই প্রয়োজন!
স্টারফ্রি

@ স্টারফ্রি, একটি সাব-শেলটিতে চালিত হওয়ার rmdir $(popd)কারণ popdযার অর্থ এটি বর্তমান ডিরেক্টরিটি পরিবর্তন করবে না, তবে এটি যদি একটি সাব-শেলটিতে চালিত না হয় তবে এর আউটপুট popdঅস্থায়ী ডিরেক্টরি হবে না, এটি একটি স্থান পৃথকীকরণ তালিকা হবে ডিরেক্টরি যে টেম্পার dir সহ না। আমি যেখানে বলছি আপনি বিভ্রান্ত
স্টাফেন চেজেলাস

তবে আমি ভেবেছিলাম যে আমি আমার প্রশ্নের মধ্যে বলেছিলাম: "পপড পপড ডিরেক্টরিটি ফিরিয়ে দেয় না (এটি নতুন, এখনকার বর্তমান, ডিরেক্টরিটি ফেরত দেয়) এবং কারণ এটি একটি সাবশেলে সঞ্চালিত হয়েছে।" স্বীকারযোগ্যভাবে এটি একটি তালিকা দেয়, তবে তালিকার প্রথমটিই আমি উল্লেখ করছি।
স্টারফ্রি 3'16

@ স্টারফ্রি, ঠিক আছে দুঃখিত। ধরা যাক যে আমিই প্রশ্নের শিরোনাম দ্বারা বিভ্রান্ত হয়ে পড়েছিলাম এবং বাকিটি খুব যত্ন সহকারে পড়িনি।
স্টাফেন চেজেলাস

আপনার উত্তরটি এখনও ভাল ছিল এবং আমাকে সঠিক দিকে নির্দেশ করলেন। আমি কখনই এই শেল পরিবর্তনশীল সম্পর্কে জানতাম না OLDPWD। আমি অবশ্যই একদিন man bashশেষ থেকে শেষ পর্যন্ত পড়তে হবে !
স্টারফ্রি

2

ডিরেক্টরিটি রেখে যাওয়ার আগে আপনি প্রথমে লিঙ্কমুক্ত করতে পারেন:

rmdir "$(pwd -P)" && popd

অথবা

rmdir "$(pwd -P)" && cd ..   # yes, .. is still usable

তবে মনে রাখবেন pushdএবং popdএগুলি সত্যই ইন্টারেক্টিভ শেলগুলির জন্য সরঞ্জাম, স্ক্রিপ্টগুলির জন্য নয় (এ কারণেই তারা এত চটকদার; সত্যিকারের স্ক্রিপ্টিং কমান্ডগুলি সাফল্যের সাথে নিরব থাকে)।


0

বাশ-এ, dirsপুশড / পপড পদ্ধতি দ্বারা স্মরণ করা ডিরেক্টরিগুলির একটি তালিকা সরবরাহ করুন।

এছাড়াও, dirs -1তালিকার অন্তর্ভুক্ত সর্বশেষ ডিরেক্টরি মুদ্রণ করে।

সুতরাং, নির্বাহ করে পূর্বে তৈরি ডিরেক্টরিটি সরিয়ে ফেলতে pushd $(mktmp -d), ব্যবহার করুন:

rmdir $(dirs -1)

এবং তারপরে, popdতালিকা থেকে ইতিমধ্যে সরানো ডিরেক্টরি:

popd > /dev/null

সমস্ত এক লাইনে:

rmdir $(dirs -1); popd > /dev/null

~/xবা ~user/xস্বরলিপি এড়ানোর জন্য বিকল্প (-l) যুক্ত করুন :

rmdir $(dirs -l -1); popd > /dev/null

যা আপনার কাছে জিজ্ঞাসা করা লাইনের সাথে উল্লেখযোগ্য অনুরূপ similar
ছাড়া আমি ব্যবহার করবে না &>যেমন করে যে কোনো এরর রিপোর্টিং লুকাতে হবে popd

দ্রষ্টব্য: ডিরেক্টরিটি rmdirসেই pwdসময়ে যেমন থাকবে তেমন থাকবে । এবং popdকমান্ডের পরে আসলে লিঙ্কযুক্ত হবে (কোনও অবশিষ্ট লিঙ্ক ব্যবহার করা হয়নি)।


"ওলডিপিডাব্লুডি" পরিবর্তনশীল (বেশিরভাগ বোর্নের মতো শেল: ksh, বাশ, zsh আছে $OLDPWD) সমর্থন করে এমন শেলগুলির জন্য ব্যবহারের একটি বিকল্প রয়েছে । এটি লক্ষণীয় যে আকর্ষণীয় যে ksh ডিয়ার, পোড, ডিফল্টরূপে চাপানো প্রয়োগ করে না (lksh, ড্যাশ এবং অন্যদেরও পপড পাওয়া যায় না, সুতরাং, এখানে ব্যবহারযোগ্য নয়):

popd && rmdir "$OLDPWD"

বা, আরও অহঙ্কারী (উপরের মতো শেলের একই তালিকা):

popd && rmdir ~-

এটির সাথে সমস্যা এবং আমি কী সমাধান rmdirকরতে চাইছি তা হ'ল আপনি যখন বর্তমান ডিরেক্টরিটি করতে পারবেন না তখন এটি করার সময় আপনি কোথায় থাকবেন। এটি popdকরার আগে আপনাকে অবশ্যই প্রভাব ফেলতে হবে rmdirতবে আপনাকে কী সরিয়ে ফেলতে হবে তা জানতে হবে এবং popdএটি আপনাকে জানায় না। আমি, আপনার মতোই dirs -l -1উত্তরটি ভেবেছিলাম তবে আমি আবিষ্কার করেছি যে উত্তরটি আসলে ব্যবহার করা $OLDPWD
স্টারফ্রি 4'16

@starfry আমি বিশ্বাস করি যে সবচেয়ে কম উত্তর ব্যবহারের হল: popd && rmdir ~-

@ স্টারফ্রি আপনি প্রকৃতপক্ষে বর্তমান ডিরেক্টরিটি সরিয়ে ফেলতে পারেন, কোনও সমস্যা নেই, শর্ত থাকলে তা খালি থাকে (মুছে ফেলতে বাধ্য না করে)। এমনকি আপনি ঠিক আছে কল করতে পারে rmdir "$PWD"। এছাড়াও, বর্তমান ডিরেক্টরিটি তৈরি করা উচিত mktmp -d(যদি pushd $(mktemp -d)আগেই কার্যকর করা হয়েছিল) এবং যা pushdপিডব্লিউডি সরায়। সুতরাং, হ্যাঁ, পপডের পরে pushd এবং তার আগে , তৈরি ডিরেক্টরিটি সংরক্ষণ করা হয় $(dirs -1), আমি কোনও সমস্যা দেখতে ব্যর্থ হই।
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.