কেন আমার শেল স্ক্রিপ্টটি সাদা স্থান বা অন্যান্য বিশেষ চরিত্রগুলিতে শ্বাসরোধ করে?


284

বা, শক্ত ফাইল ফাইল হ্যান্ডলিং এবং শেল স্ক্রিপ্টগুলিতে পাস করা অন্যান্য স্ট্রিংয়ের একটি প্রাথমিক নির্দেশিকা।

আমি একটি শেল স্ক্রিপ্ট লিখেছিলাম যা বেশিরভাগ সময় ভাল কাজ করে। তবে এটি কিছু ইনপুটগুলিকে (যেমন কিছু ফাইলের নামের উপরে) চাপিয়ে দেয়।

আমি নিম্নলিখিতগুলির মতো একটি সমস্যার মুখোমুখি হয়েছি:

  • আমার কাছে একটি ফাইলের নাম রয়েছে যাতে একটি স্থান থাকে hello worldএবং এটি দুটি পৃথক ফাইল helloএবং হিসাবে বিবেচিত হয় world
  • আমার কাছে একটানা দুটি স্পেস সহ একটি ইনপুট লাইন রয়েছে এবং তারা ইনপুটটিতে একটিতে সঙ্কুচিত হয়।
  • নেতৃস্থানীয় এবং পিছনের শ্বেত স্পেস ইনপুট লাইনগুলি থেকে অদৃশ্য হয়ে যায়।
  • কখনও কখনও, যখন ইনপুটটিতে অক্ষরগুলির একটি থাকে \[*?তখন এগুলি কিছু পাঠ্য দ্বারা প্রতিস্থাপন করা হয় যা আসলে ফাইলগুলির নাম।
  • ইনপুটটিতে একটি অ্যাডাস্ট্রোফ '(বা একটি ডাবল উদ্ধৃতি ") রয়েছে এবং জিনিসগুলি সেই বিন্দুর পরে অদ্ভুত হয়ে পড়ে।
  • ইনপুটটিতে একটি ব্যাকস্ল্যাশ রয়েছে (বা: আমি সাইগউইন ব্যবহার করছি এবং আমার কিছু ফাইলের নামের উইন্ডোজ-স্টাইল \বিভাজক রয়েছে)।

কী চলছে এবং আমি কীভাবে এটি ঠিক করব?


16
shellcheckআপনার প্রোগ্রামের মান উন্নত করতে আপনাকে সহায়তা করে।
অরেলিন

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


1
@ ব্লি না, এটি কেবল বাগগুলি আপ করতে আরও বেশি সময় নেয়। এটি আজ বাগগুলি লুকিয়ে রাখছে। এবং এখন, আপনি নিজের কোড সহ পরে ব্যবহৃত সমস্ত ফাইলের নাম জানেন না।
ভোলকার সিগেল

প্রথমে, যদি আপনার প্যারামিটারগুলিতে স্পেস থাকে তবে সেগুলি (কমান্ড লাইনে) goingুকে গিয়ে उद्धृत করা দরকার। তবে আপনি পুরো কমান্ড লাইনটি দখল করতে পারেন এবং এটি নিজের বিশ্লেষণ করতে পারেন। দুটি স্পেস এক জায়গায় পরিণত হয় না; যে কোনও পরিমাণ স্পেস আপনার স্ক্রিপ্টকে বলে দেয় যা পরবর্তী পরিবর্তনশীল তাই যদি আপনি "প্রতিধ্বনি $ 1 $ 2" এর মতো কিছু করেন তবে এটি আপনার স্ক্রিপ্টের মধ্যে একটি স্থান রেখে দেবে। লুপের পরিবর্তে ফাঁকা জায়গায় ফাইলগুলি পুনরাবৃত্তি করতে "ফাইন্ড (-এক্সেক)" ব্যবহার করুন; আপনি স্পেসগুলি আরও সহজেই মোকাবেলা করতে পারেন।
প্যাট্রিক টেলর

উত্তর:


352

সর্বদা পরিবর্তনশীল বদল ও কমান্ড বদল প্রায় উদ্ধৃতি চিহ্ন ব্যবহার করুন: "$foo","$(foo)"

আপনি যদি $fooঅব্যক্ত ব্যবহার করেন তবে আপনার স্ক্রিপ্টটি ইনপুট বা প্যারামিটারগুলিতে (বা কমান্ড আউটপুট, দিয়ে $(foo)) শ্বেতস্পেস বা চিট করবে \[*?

সেখানে, আপনি পড়া বন্ধ করতে পারেন। ঠিক আছে, ঠিক আছে, এখানে আরও কয়েকটি রয়েছে:

  • read- বিল্টিনের সাথে readসামঞ্জস্য রেখে ইনপুট লাইনটি পড়ার জন্য ,while IFS= read -r line; do … বিশেষভাবে
    সমতল readআচরণের ব্যাকস্ল্যাশ এবং হোয়াইটস্পেস ব্যবহার করুন
  • xargs- এড়ানোxargs । আপনি যদি অবশ্যই ব্যবহার করেন তবে xargsএটি তৈরি করুন xargs -0। পরিবর্তে find … | xargs, পছন্দfind … -exec …
    xargsশ্বেতস্থান এবং চরিত্রগুলি \"'বিশেষভাবে বিবেচনা করে।

এই উত্তরটি বোর্ন / POSIX ধাঁচের শাঁস (প্রযোজ্য sh, ash, dash, bash, ksh, mksh, yash...)। Zsh ব্যবহারকারীদের এটি এড়িয়ে যাওয়া উচিত এবং ডাবল-কোটিংয়ের প্রয়োজনীয়তা কখন শেষ করা উচিত ? পরিবর্তে. আপনি যদি পুরো ব্যস্ততা চান, মান বা আপনার শেলের ম্যানুয়ালটি পড়ুন।


নোট করুন যে নীচের ব্যাখ্যায় কয়েকটি আনুমানিকতা রয়েছে (বিবৃতি যা বেশিরভাগ ক্ষেত্রে সত্য তবে পার্শ্ববর্তী প্রসঙ্গে বা কনফিগারেশন দ্বারা প্রভাবিত হতে পারে)।

আমার লেখার দরকার কেন "$foo"? উদ্ধৃতি ছাড়া কি হয়?

$foo"ভেরিয়েবলের মান গ্রহণ করুন" এর অর্থ এই নয় foo। এর অর্থ আরও জটিল কিছু:

  • প্রথমে ভেরিয়েবলের মান নিন।
  • ক্ষেত্র বিভাজন: সেই মানটিকে একটি সাদা ক্ষেত্র-বিচ্ছিন্ন ক্ষেত্রের তালিকা হিসাবে বিবেচনা করুন এবং ফলাফলটি তৈরি করুন। উদাহরণস্বরূপ, পরিবর্তনশীল থাকে foo * bar ​তাহলে এই পদক্ষেপ ফল 3-উপাদান তালিকা foo, *, bar
  • ফাইলের নাম জেনারেশন: প্রতিটি ক্ষেত্রকে একটি গ্লোব হিসাবে বিবেচনা করুন, যেমন একটি ওয়াইল্ডকার্ড প্যাটার্ন হিসাবে, এবং এই প্যাটার্নের সাথে মেলে এমন ফাইলের নামের সাথে এটি প্রতিস্থাপন করুন। যদি প্যাটার্নটি কোনও ফাইলের সাথে মেলে না, তবে এটি অশোধিত ছেড়ে দেওয়া হবে। আমাদের উদাহরণস্বরূপ, fooবর্তমান ডিরেক্টরিতে ফাইলগুলির তালিকা অনুসরণ করে এবং শেষ পর্যন্ত এই ফলাফলের ফলাফল রয়েছে bar। তাহলে বর্তমান ডিরেক্টরী খালি থাকে, ফল foo, *, bar

নোট করুন যে ফলাফলটি স্ট্রিংগুলির একটি তালিকা। শেল সিনট্যাক্সে দুটি কনটেক্সট রয়েছে: তালিকা প্রসঙ্গে এবং স্ট্রিং প্রসঙ্গে। ফিল্ড বিভাজন এবং ফাইলের নাম উত্পাদন কেবল তালিকা প্রসঙ্গে হয়, তবে এটি বেশিরভাগ সময়। ডাবল উদ্ধৃতিগুলি একটি স্ট্রিং প্রসঙ্গে ডিলিট করে: পুরো ডাবল-কোটেড স্ট্রিংটি একটি একক স্ট্রিং, বিভক্ত হতে হবে না। (ব্যতিক্রম: "$@"অবস্থানগত প্যারামিটারগুলির তালিকায় প্রসারিত করার জন্য, যেমন তিনটি অবস্থানগত পরামিতি রয়েছে "$@"সমান "$1" "$2" "$3"See দেখুন * and * এবং $ @ এর মধ্যে পার্থক্য কী? )

একই সাথে $(foo)বা এর সাথে বিকল্পের আদেশের ক্ষেত্রেও ঘটে `foo`। সাইড নোটে, ব্যবহার করবেন না `foo`: এর উদ্ধৃতি বিধিগুলি অদ্ভুত এবং অ-বহনযোগ্য এবং সমস্ত আধুনিক শেল সমর্থন করে $(foo)যা স্বজ্ঞাত উদ্ধৃতি বিধি ব্যতীত একেবারে সমতুল্য।

পাটিগণিত প্রতিস্থাপনের আউটপুটও একই বিস্তৃতি বহন করে, তবে এটি সাধারণত উদ্বেগের বিষয় নয় কারণ এতে কেবল অ-প্রসারণযোগ্য অক্ষর রয়েছে (ধরে নেওয়া যায় IFSযে সংখ্যাগুলি নেই বা রয়েছে -)।

দেখুন কখন ডাবল-কোটিং দরকার? মামলাগুলি সম্পর্কে আরও বিশদের জন্য যখন আপনি উদ্ধৃতিগুলি ছাড়তে পারেন।

যদি না আপনি এই সমস্ত প্রতিবন্ধকতা ঘটানোর জন্য বোঝাতে চান তবে কেবল ভেরিয়েবল এবং কমান্ড বিকল্পের পরিবর্তে সর্বদা ডাবল উদ্ধৃতি ব্যবহার করা মনে রাখবেন। যত্ন নিন: উদ্ধৃতিগুলি না রেখে কেবল ত্রুটিই নয় সুরক্ষা গর্তের দিকেও যেতে পারে ।

আমি কীভাবে ফাইলের নামের একটি তালিকা প্রক্রিয়া করব?

আপনি যদি myfiles="file1 file2"ফাইলগুলি পৃথক করার জন্য স্পেস দিয়ে লিখেন তবে এটি ফাঁকা থাকা ফাইলের নামের সাথে কাজ করতে পারে না। ইউনিক্স ফাইলের নামগুলিতে /(যা সর্বদা ডিরেক্টরি বিভাজক) এবং নাল বাইট (যা আপনি বেশিরভাগ শেল সহ শেল স্ক্রিপ্টগুলিতে ব্যবহার করতে পারবেন না) ব্যতীত অন্য কোনও অক্ষর ধারণ করতে পারে ।

একই সমস্যা myfiles=*.txt; … process $myfiles। আপনি যখন এটি করেন, ভেরিয়েবলটিতে myfiles5-অক্ষরের স্ট্রিং থাকে *.txtএবং আপনি যখন লিখবেন $myfilesযে ওয়াইল্ডকার্ডটি প্রসারিত। আপনি নিজের স্ক্রিপ্টটিকে পরিবর্তন না করা পর্যন্ত এই উদাহরণটি আসলে কাজ করবে myfiles="$someprefix*.txt"; … process $myfiles। যদি someprefixসেট করা থাকে তবে এটি final reportকাজ করবে না।

যে কোনও ধরণের তালিকার প্রক্রিয়া করতে (যেমন ফাইলের নাম), এটি অ্যারেতে রাখুন। এর জন্য mksh, ksh93, যশ বা বাশ (বা zsh, যা এই সমস্ত উদ্ধৃতি সংক্রান্ত সমস্যাগুলির মধ্যে নেই) প্রয়োজন; একটি সরল POSIX শেল (যেমন ছাই বা ড্যাশ) এর অ্যারে ভেরিয়েবলগুলি নেই।

myfiles=("$someprefix"*.txt)
process "${myfiles[@]}"

Ksh88 এর বিভিন্ন অ্যাসাইনমেন্ট সিনট্যাক্স সহ অ্যারে ভেরিয়েবল রয়েছে set -A myfiles "someprefix"*.txt( আপনার যদি ksh88 / ব্যাশ বহনযোগ্যতার প্রয়োজন হয় তবে বিভিন্ন ksh পরিবেশের অধীনে অ্যাসাইনমেন্ট ভেরিয়েবল দেখুন )। বোর্ন / পসআইএক্স-স্টাইল শেলগুলির একটি একক অ্যারে থাকে, আপনি যে পজিশনাল প্যারামিটারগুলির সাথে অ্যারে "$@"সেট করেন setএবং যা কোনও ফাংশনে লোকাল তা:

set -- "$someprefix"*.txt
process -- "$@"

ফাইল নামগুলির সাথে -কী শুরু হয় ?

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

বিকল্পভাবে, আপনি নিশ্চিত করতে পারেন যে আপনার ফাইলের নামগুলি ব্যতীত অন্য একটি অক্ষর দিয়ে শুরু হয় -। সম্পূর্ণ ফাইলের নামগুলি শুরু হয় /এবং আপনি ./আপেক্ষিক নামের শুরুতে যুক্ত করতে পারেন । নীচের স্নিপেটটি ভেরিয়েবলের সামগ্রীটি fএকই ফাইলটিতে পুনরায় উল্লেখ করার "নিরাপদ" উপায়ে রূপান্তরিত করে যা শুরু না করার গ্যারান্টিযুক্ত -

case "$f" in -*) "f=./$f";; esac

এই বিষয়টির একটি চূড়ান্ত নোটে, সাবধান থাকুন যে কোনও কোনও কমান্ড -স্ট্যান্ডার্ড ইনপুট বা স্ট্যান্ডার্ড আউটপুট এমনকি পরে বোঝায় --। যদি আপনাকে নামের কোনও আসল ফাইলটি উল্লেখ করতে হয় -বা আপনি যদি এই জাতীয় প্রোগ্রামটি কল করে থাকেন এবং আপনি এটি স্টিডিন থেকে পড়তে বা স্টডআউটে লিখতে না চান তবে -উপরের মত পুনরায় লেখার বিষয়টি নিশ্চিত করুন । দেখুন "du -sh *" এবং "du -sh ./*" এর মধ্যে পার্থক্য কী? আরও আলোচনার জন্য।

আমি একটি চলকটিতে একটি কমান্ড কীভাবে সংরক্ষণ করব?

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

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

command_path="$1"

"$command_path" --option --message="hello world"

আপনার যদি আর্গুমেন্ট সহ একটি কমান্ড থাকে, সমস্যাটি উপরের ফাইল নামের তালিকার মতোই: এটি স্ট্রিংগুলির তালিকা নয়, স্ট্রিং নয়। আপনি কেবলমাত্র একক স্ট্রিংয়ের মধ্যে ফাঁক দিয়ে আর্গুমেন্টগুলি স্টাফ করতে পারবেন না, কারণ আপনি যদি এটি করেন তবে আপনি যুক্তিগুলির অংশ এবং ফাঁকা স্থানগুলির মধ্যে পৃথক যুক্তিগুলির স্পেসের মধ্যে পার্থক্য বলতে পারবেন না। যদি আপনার শেলটিতে অ্যারে থাকে তবে আপনি সেগুলি ব্যবহার করতে পারেন।

cmd=(/path/to/executable --option --message="hello world" --)
cmd=("${cmd[@]}" "$file1" "$file2")
"${cmd[@]}"

আপনি যদি অ্যারে ছাড়াই শেল ব্যবহার করছেন? আপনি এখনও অবস্থানগত প্যারামিটারগুলি ব্যবহার করতে পারেন, যদি সেগুলি সংশোধন করতে আপনার আপত্তি না থাকে।

set -- /path/to/executable --option --message="hello world" --
set -- "$@" "$file1" "$file2"
"$@"

আপনার যদি কোনও জটিল শেল কমান্ড, যেমন পুনঃনির্দেশ, পাইপ ইত্যাদির সাথে সঞ্চয় করতে হয়? বা আপনি যদি অবস্থানগত পরামিতিগুলি পরিবর্তন করতে চান না? তারপরে আপনি কমান্ড যুক্ত একটি স্ট্রিং তৈরি করতে পারেন এবং evalবিল্টিন ব্যবহার করতে পারেন ।

code='/path/to/executable --option --message="hello world" -- /path/to/file1 | grep "interesting stuff"'
eval "$code"

সংজ্ঞায় নেস্টেড কোটগুলি নোট করুন code: একক উদ্ধৃতিগুলি '…'একটি স্ট্রিং আক্ষরিকভাবে সীমিত করে দেয়, যাতে ভেরিয়েবলের মান codeস্ট্রিং হয় /path/to/executable --option --message="hello world" -- /path/to/file1evalBuiltin শেল বলে স্ট্রিং হিসেবে যদি এটা স্ক্রিপ্ট হাজির একটি আর্গুমেন্ট হিসাবে পাস বিশ্লেষণ করতে, যাতে সময়ে কোট এবং পাইপ পার্স করা হয়, ইত্যাদি

ব্যবহার evalকরা কঠিন। কখন পার্স করা যায় সে সম্পর্কে সাবধানতার সাথে চিন্তা করুন। বিশেষত, আপনি কেবল কোডে কোনও ফাইলের নাম স্টাফ করতে পারবেন না: আপনার যেমনটি উত্স কোড ফাইলে থাকত তেমনই আপনাকে এটিকে উদ্ধৃত করতে হবে। এটি করার সরাসরি কোনও উপায় নেই। ভালো কিছু code="$code $filename"বিরতি যদি ফাইল নামের কোনো শেল বিশেষ অক্ষর আছে (স্পেস, $, ;, |, <, >, ইত্যাদি)। code="$code \"$filename\""এখনও বিরতি "$\`। এমনকি code="$code '$filename'"বিরতি যদি ফাইল নামের একটি রয়েছে '। দুটি সমাধান আছে।

  • ফাইলের নামের চারপাশে উদ্ধৃতিগুলির একটি স্তর যুক্ত করুন। এটি করার সবচেয়ে সহজ উপায় হল এর চারপাশে একক উদ্ধৃতি যুক্ত করা এবং একক উদ্ধৃতি দ্বারা প্রতিস্থাপন করা '\''

    quoted_filename=$(printf %s. "$filename" | sed "s/'/'\\\\''/g")
    code="$code '${quoted_filename%.}'"
    
  • কোডের অভ্যন্তরে ভেরিয়েবল প্রসারিত রাখুন, যাতে কোডটি মূল্যায়ন করার সময় সন্ধান করা হয়, কোড খণ্ডটি নির্মিত না হয়ে নয়। এটি সহজ তবে কেবল তখনই কার্যকর হয় যখন কোডটি কার্যকর করার সময় ভেরিয়েবল একই মান সহ প্রায় থাকে তবে উদাহরণস্বরূপ নয় কোডটি কোনও লুপে নির্মিত কিনা।

    code="$code \"\$filename\""

শেষ অবধি, আপনার কি সত্যিকারের কোডযুক্ত একটি ভেরিয়েবলের প্রয়োজন? কোড ব্লকে নাম দেওয়ার সর্বাধিক প্রাকৃতিক উপায় হ'ল কোনও ফাংশন সংজ্ঞায়িত করা।

কি হয়েছে read?

ছাড়া -r, readধারাবাহিকতা রেখাগুলি অনুমতি দেয় - এটি ইনপুটটির একক লজিকাল লাইন:

hello \
world

readইনপুট লাইনটি অক্ষর দ্বারা সীমানাযুক্ত ক্ষেত্রগুলিতে বিভক্ত করে $IFS(ব্যতীত -r, ব্যাকস্ল্যাশগুলিও সেগুলি এড়িয়ে যায়)। উদাহরণস্বরূপ, যদি ইনপুটটি তিনটি শব্দের সমন্বিত একটি লাইন হয়, তবে read first second thirdইনপুটটির firstপ্রথম শব্দের সাথে, secondদ্বিতীয় শব্দের সাথে এবং thirdতৃতীয় শব্দের সাথে সেট করে। যদি আরও শব্দ থাকে তবে শেষের ভেরিয়েবলটিতে পূর্বেরগুলি সেট করার পরে বাকি সমস্ত কিছু রয়েছে। শীর্ষস্থানীয় এবং পিছনের সাদা অংশ ছাঁটাই করা হয়।

IFSখালি স্ট্রিংয়ে সেট করা কোনও ছাঁটাই এড়ায়। দেখুন কেন `যখন IFS = read` তাই প্রায়ই, এর পরিবর্তে 'এর IFS = ব্যবহার করা হয়; পড়ার সময়..`? একটি দীর্ঘ ব্যাখ্যার জন্য।

এর সাথে কী হয়েছে xargs?

এর ইনপুট ফর্ম্যাটটি xargsহোয়াইটস্পেস-বিচ্ছিন্ন স্ট্রিং যা allyচ্ছিকভাবে একক- বা ডাবল-কোটেড হতে পারে। কোনও মানক সরঞ্জাম এই ফর্ম্যাটটিকে আউটপুট দেয় না।

ইনপুট xargs -L1বা xargs -lপ্রায় লাইনের একটি তালিকা বেশ, কিন্তু না - একটি লাইন শেষে ব্যবধান আছে তা হলে, নিম্নলিখিত লাইন ধারাবাহিকতায় লাইন।

xargs -0প্রযোজ্য যেখানে আপনি ব্যবহার করতে পারেন (এবং যেখানে উপলব্ধ: জিএনইউ (লিনাক্স, সাইগউইন), ব্যাসিবক্স, বিএসডি, ওএসএক্স, তবে এটি পসিক্সে নেই)। এটি নিরাপদ, কারণ নাল বাইটগুলি বেশিরভাগ ডেটাতে দেখা যায় না, বিশেষত ফাইলের নামগুলিতে। ফাইলের নামের একটি নাল দ্বারা পৃথক করা তালিকা তৈরি find … -print0করতে ব্যবহার করুন (বা আপনি find … -exec …নীচে বর্ণিত হিসাবে ব্যবহার করতে পারেন )।

আমি ফাইলগুলি কীভাবে প্রক্রিয়াকরণ করব find?

find  -exec some_command a_parameter another_parameter {} +

some_commandএকটি বাহ্যিক কমান্ড হওয়া দরকার, এটি শেল ফাংশন বা ওরফে হতে পারে না। ফাইলগুলি প্রক্রিয়া করার জন্য যদি আপনাকে শেলটি চাওয়ার প্রয়োজন হয় তবে shস্পষ্টভাবে কল করুন ।

find  -exec sh -c '
  for x do
    … # process the file "$x"
  done
' find-sh {} +

আমার আরও কিছু প্রশ্ন আছে

এই সাইটে বা বা ট্যাগ ব্রাউজ করুন । (কিছু সাধারণ টিপস এবং সাধারণ প্রশ্নগুলির একটি হাতে-নির্বাচিত তালিকা দেখতে "আরও শিখুন ..." এ ক্লিক করুন you've) আপনি যদি অনুসন্ধান করেছেন এবং উত্তর খুঁজে না পেয়ে থাকেন, তবে জিজ্ঞাসা করুন


6
@ জন 1024 এটি কেবল একটি জিএনইউ বৈশিষ্ট্যযুক্ত, তাই আমি "কোনও মানক সরঞ্জাম নেই" দিয়ে থাকব।
গিলস

2
আপনার কাছাকাছি $(( ... ))( $[...]কিছু শেলের মধ্যেও ) ছাড়াও zsh(এমনকি শের অনুকরণে) এবং এর বাইরেও আপনার প্রয়োজন হবে mksh
স্টাফেন চেজেলাস

3
দ্রষ্টব্য যে xargs -0পসিক্স নয়। ফ্রিবিএসডি বাদে xargsআপনি সাধারণত এর xargs -r0পরিবর্তে চান xargs -0
স্টাফেন চেজেলাস

2
@ জন 1024, না, ls --quoting-style=shell-alwaysএর সাথে সামঞ্জস্যপূর্ণ নয় xargs। চেষ্টা করুনtouch $'a\nb'; ls --quoting-style=shell-always | xargs
স্টাফেন চেজেলাস

3
আরেকটি চমৎকার (গনুহ-শুধুমাত্র) বৈশিষ্ট্য xargs -d "\n"যাতে আপনি যেমন চালাতে পারেন locate PATTERN1 |xargs -d "\n" grep PATTERN2ফাইল মিলে নাম জন্য অনুসন্ধান করতে PATTERN1 বিষয়বস্তু ম্যাচিং সঙ্গে PATTERN2 । জিএনইউ ছাড়া আপনি এটি যেমন উদাহরণস্বরূপ করতে পারেনlocate PATTERN1 |perl -pne 's/\n/\0/' |xargs -0 grep PATTERN1
অ্যাডাম কাটজ

26

যদিও গিলস উত্তরটি দুর্দান্ত, আমি তার মূল বিষয়টিতে বিষয়টি নিয়েছি

পরিবর্তনশীল বিকল্প এবং কমান্ড বিকল্পের চারপাশে সর্বদা ডাবল উদ্ধৃতি ব্যবহার করুন: "oo foo", "$ (foo)"

যখন আপনি কোনও বাশ-জাতীয় শেল দিয়ে শুরু করছেন যা শব্দ বিভাজন করে, হ্যাঁ অবশ্যই নিরাপদ পরামর্শ সর্বদা উদ্ধৃতি ব্যবহার করা। তবে শব্দ বিভাজন সবসময় করা হয় না

§ শব্দ বিভাজন

এই আদেশগুলি ত্রুটি ছাড়াই চালানো যেতে পারে

foo=$bar
bar=$(a command)
logfile=$logdir/foo-$(date +%Y%m%d)
PATH=/usr/local/bin:$PATH ./myscript
case $foo in bar) echo bar ;; baz) echo baz ;; esac

আমি ব্যবহারকারীদের এই আচরণ অবলম্বন করতে উত্সাহিত করছি না, তবে শব্দ বিভাজন ঘটে যখন কেউ দৃly়ভাবে বুঝতে পারে তবে কোট ব্যবহার করার সময় তাদের নিজেরাই সিদ্ধান্ত নিতে সক্ষম হওয়া উচিত।


19
আমি আমার উত্তরে যেমন উল্লেখ করেছি, বিশদর জন্য unix.stackexchange.com/questions/68694/… দেখুন। প্রশ্নটি লক্ষ্য করুন - "কেন আমার শেল স্ক্রিপ্ট চট করে?" সর্বাধিক সাধারণ সমস্যা (এই সাইটে এবং অন্য কোথাও বছরের অভিজ্ঞতা থেকে) ডাবল উক্তি অনুপস্থিত। "সর্বদা ডাবল কোট ব্যবহার করুন" মনে রাখা সহজ "সর্বদা ডাবল কোট ব্যবহার করুন, এই ক্ষেত্রেগুলি যেখানে প্রয়োজন হয় না সেগুলি বাদে"।
গিলস

14
নিয়মগুলি প্রাথমিকভাবে বুঝতে অসুবিধাজনক। উদাহরণস্বরূপ, foo=$barঠিক আছে, export foo=$barবা env foo=$varনা হয় (অন্তত কিছু শেলের মধ্যে)। শিক্ষানবিস জন্য একটি পরামর্শ: যদি না আপনি জানেন আপনি কি করছেন এবং একটি ভাল কারণ না আছে সবসময় আপনার ভেরিয়েবল উদ্ধৃত
স্টাফেন চেজেলাস

5
পুনঃটুইট করেছেন এমন কোনও যুক্তিসঙ্গত মামলা রয়েছে যেখানে উদ্ধৃতিগুলি স্ক্রিপ্টটি ভেঙে দেয়? এমন পরিস্থিতিতে যেখানে অর্ধেক ক্ষেত্রে কোট অবশ্যই ব্যবহার করা উচিত , এবং অন্য অর্ধে উদ্ধৃতিতে বিকল্পভাবে ব্যবহার করা যেতে পারে - তারপরে একটি প্রস্তাবনা "সর্বদা উদ্ধৃতি ব্যবহার করুন, কেবলমাত্র ক্ষেত্রে" এটিই ভাবা উচিত, যেহেতু এটি সত্য, সহজ এবং ঝুঁকিপূর্ণ। প্রাথমিকভাবে ব্যাতিক্রমের এই জাতীয় তালিকা শেখানো অকার্যকর হিসাবে পরিচিত (প্রসঙ্গের অভাব, তারা তাদের মনে রাখবেন না) এবং প্রতিক্রিয়াশীল, কারণ তারা প্রয়োজনীয় / অপরিশোধিত উদ্ধৃতিগুলি বিভ্রান্ত করবেন, তাদের স্ক্রিপ্টগুলি ভেঙে ফেলবেন এবং আরও শিখতে তাদের demotivating করবেন।
পিটারিস

6
আমার $ 0.02 হবে যে সমস্ত কিছু উদ্ধৃত করার পরামর্শ দেওয়া ভাল পরামর্শ। ভুলভাবে এমন কিছু উদ্ধৃত করা যা তার প্রয়োজন হয় না তা ক্ষতিগ্রস্থ, ভুলভাবে এমন কিছু উদ্ধৃত করতে ব্যর্থ হয় যা এর জন্য ক্ষতিকারক। সুতরাং, বেশিরভাগ শেল স্ক্রিপ্ট লেখক যারা কখনই শব্দ বিভাজন ঘটে তার জটিলতা কখনই বুঝতে পারবেন না, কেবল যেখানে প্রয়োজন সেখানে উদ্ধৃতি দেওয়ার চেয়ে সমস্ত কিছু উদ্ধৃত করা অনেক বেশি নিরাপদ।
গডলিজিক

5
@ পিটারিস এবং গডলিজিক: "এমন কোনও যুক্তিসঙ্গত মামলা রয়েছে যেখানে উদ্ধৃতিগুলি স্ক্রিপ্টটি ভেঙে দেয়?" এটি আপনার "যুক্তিসঙ্গত" সংজ্ঞা নির্ভর করে। যদি কোনও স্ক্রিপ্ট সেট হয় criteria="-type f", তবে find . $criteriaকাজ করে তবে কার্যকর find . "$criteria"হয় না।
জি ম্যান

22

আমি যতদূর জানি, কেবলমাত্র দুটি মামলা রয়েছে যার ক্ষেত্রে দ্বিগুণ-উদ্ধৃতি বিস্তৃত হওয়া প্রয়োজন, এবং এই ক্ষেত্রে দুটি বিশেষ শেল প্যারামিটার জড়িত "$@"এবং "$*"- যা ডাবল-কোয়েটে আবদ্ধ হয়ে আলাদাভাবে প্রসারিত করার জন্য নির্দিষ্ট করা হয়। অন্যান্য সমস্ত ক্ষেত্রে (সম্ভবত শেল-নির্দিষ্ট অ্যারে বাস্তবায়নগুলি বাদ দিয়ে) কোনও প্রসারণের আচরণ একটি কনফিগারযোগ্য জিনিস - এটির জন্য বিকল্প রয়েছে।

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

শেল, তার হৃদয় ও আত্মা (যাদের আছে যে এই ধরনের জন্য) , এটি একটি পার্সার হয় একটি বড়, ইন্টারেক্টিভ মত - একটি কম্যান্ড-ব্যাখ্যাকারী হয় sed। যদি আপনার শেল স্টেটমেন্ট শ্বেতস্থান বা অনুরূপভাবে দম বন্ধ হয়ে থাকে তবে এটি সম্ভবত খুব সম্ভবত কারণ আপনি শেলের ব্যাখ্যা প্রক্রিয়াটি পুরোপুরি বুঝতে পারেন নি - বিশেষত কীভাবে এবং কেন এটি একটি কার্যক্ষম কমান্ডে একটি ইনপুট বিবৃতি অনুবাদ করে। শেলের কাজটি হ'ল:

  1. ইনপুট গ্রহণ করুন

  2. টোকেনাইজড ইনপুট শব্দগুলিতে এটিকে সঠিকভাবে ব্যাখ্যা এবং ভাগ করুন split

    • ইনপুট শব্দগুলি হ'ল শেল সিনট্যাক্স আইটেম যেমন $wordorecho $words 3 4* 5

    • শব্দগুলি সর্বদা হোয়াইটস্পেসে বিভক্ত থাকে - এটি কেবল সিনট্যাক্স - তবে কেবল ইনপুট ফাইলে শাবরে কেবল আক্ষরিক শ্বেতক্ষেত্রের অক্ষরই পরিবেশন করা হয়

  3. প্রয়োজনে একাধিক ক্ষেত্রে প্রসারিত করুন

    • ক্ষেত্রগুলি শব্দ বিস্তারের ফলে ঘটে - এগুলি চূড়ান্ত সম্পাদনযোগ্য কমান্ড তৈরি করে

    • বাদ "$@", $IFS ক্ষেত্র-বিভক্তকরণ এবং পথের নাম সম্প্রসারণের জন্য একটি ইনপুট শব্দ সর্বদা একক ক্ষেত্রে মূল্যায়ন করতে হবে ।

  4. এবং তারপরে ফলাফলটি কমান্ড কার্যকর করতে হবে

    • বেশিরভাগ ক্ষেত্রে এর ব্যাখ্যার ফলাফলটি কোনও না কোনও রূপে জড়িত থাকে

লোকেরা প্রায়শই বলে যে শেলটি একটি আঠালো , এবং যদি এটি সত্য হয়, তবে এটি যা আঁকছে তা হল যুক্তিগুলির - বা ক্ষেত্রগুলির তালিকা - যখন এটি হয় তখন কোনও প্রক্রিয়া বা অন্যটিতে থাকে exec। বেশিরভাগ শেলগুলি NULবাইটটি ভালভাবে পরিচালনা করে না - যদি তা হয় তবে - এবং এটি কারণ এটি ইতিমধ্যে এতে বিভক্ত। শেলটির exec অনেক কিছুই আছে এবং এটি অবশ্যই NULএটি সিস্টেমের কার্নেলের সাথে যুক্ত আর্গুমেন্টের একটি সীমানাযুক্ত অ্যারে দিয়ে করতে হবে exec। আপনি যদি শেলটির ডিলিমিটারটিকে তার সীমান্তযুক্ত ডেটা দিয়ে মিশ্রিত করতে থাকেন তবে শেলটি সম্ভবত এটি প্যাঁচিয়ে ফেলবে। এর অভ্যন্তরীণ ডেটা স্ট্রাকচারগুলি - বেশিরভাগ প্রোগ্রামের মতো - সেই ডিলিমিটারের উপর নির্ভর করে। zsh, উল্লেখযোগ্যভাবে, এই স্ক্রু না।

এবং এটি যেখানে $IFSআসে সেখানে $IFSসর্বদা উপস্থিত থাকে - এবং একইভাবে নিষ্পত্তিযোগ্য - শেল পরামিতি যা শেলটি কীভাবে শব্দ থেকে ক্ষেত্রের মধ্যে শেল প্রসারকে বিভক্ত করতে হবে তা নির্ধারণ করে - বিশেষত এই ক্ষেত্রগুলি কীভাবে মূল্যায়ন করা উচিত তার উপর । - বা, অন্য কথায় শেল বিকল্পগুলি বাইটগুলি পরিবর্তিত হয় যা এর অভ্যন্তরীণ ডেটা-অ্যারেগুলির সাথে মানগুলির সাথে মেলে তার পরিবর্তে শিটের $IFSবিস্তৃতি বিভক্ত করে। আপনি যখন এটির দিকে তাকান তখন আপনি দেখতে শুরু করতে পারেন যে প্রতিটি ক্ষেত্র-বিভক্ত শেল সম্প্রসারণ হ'ল একটি অস্বীকৃত ডেটা অ্যারে।NUL$IFSNUL$IFS

এটি বোঝা যে গুরুত্বপূর্ণ $IFSশুধুমাত্র delimits প্রসারণও যে না যা আপনার সাথে করতে পারেন - ইতিমধ্যে অন্যথায় সীমায়িত "ডাবল কোট। আপনি যখন কোনও সম্প্রসারণ উদ্ধৃত করেন তখন আপনি এটিকে মাথাতে এবং কমপক্ষে এর মানটির লেজ পর্যন্ত সীমিত করে দেন । $IFSপৃথক করার জন্য কোন ক্ষেত্র না থাকায় সেই ক্ষেত্রে প্রয়োগ হয় না does প্রকৃতপক্ষে, একটি ডাবল-কোটেড এক্সটেনশান শূন্য মান সেট করা থাকলে একটি অনাদায়ী প্রসারণে অভিন্ন ক্ষেত্র-বিভাজন আচরণ প্রদর্শন করে IFS=

উদ্ধৃতিবিহীন, $IFSনিজেই একটি $IFSসীমিত শেল সম্প্রসারণ। এটি একটি নির্দিষ্ট মানের ডিফল্ট হয় <space><tab><newline>- যার মধ্যে তিনটিই বিশেষ বৈশিষ্ট্যগুলির মধ্যে উপস্থিত থাকে $IFS। অন্য কোন মান যেখানে জন্য $IFSএকটি একক থেকে নির্ণয় করা নির্দিষ্ট করা ক্ষেত্র সম্প্রসারণ প্রতি সংঘটন , $IFS হোয়াইটস্পেস - যারা তিন কোন - সম্প্রসারণ প্রতি একটি একক মাঠে উচ্চারণ না করা থেকে নির্দিষ্ট করা ক্রম এবং নেতৃস্থানীয় / trailing সিকোয়েন্স সম্পূর্ণভাবে লুপ্ত হয়। উদাহরণস্বরূপ এটি সম্ভবত বোঝা সহজ।

slashes=///// spaces='     '
IFS=/; printf '<%s>' $slashes$spaces
<><><><><><     >
IFS=' '; printf '<%s>' $slashes$spaces
</////>
IFS=; printf '<%s>' $slashes$spaces
</////     >
unset IFS; printf '<%s>' "$slashes$spaces"
</////     >

তবে এটি ঠিক $IFS- কেবল শব্দ-বিভাজন বা হোয়াইটস্পেস যেমন জিজ্ঞাসা করা হয়েছে, তাই বিশেষ চরিত্রগুলি কী?

শেলটি - ডিফল্টরূপে - নির্দিষ্ট কিছু অব্যক্ত টোকেন (যেমন ?*[এখানে অন্যত্র উল্লিখিত) একাধিক ক্ষেত্রে প্রসারিত হবে যখন তারা তালিকায় আসে। এটিকে পথের নাম সম্প্রসারণ বা গ্লোববিং বলা হয় । এটি একটি অবিশ্বাস্যভাবে কার্যকর সরঞ্জাম এবং এটি শেলের পার্স-অর্ডারে ক্ষেত্র-বিভাজনের পরে যেমন এটি $ আইএফএস দ্বারা প্রভাবিত হয় না - একটি পথের নাম প্রসারণ দ্বারা উত্পাদিত ক্ষেত্রগুলি ফাইলের নাম / মাথাতে নির্ধারিত হয় সেগুলি নির্বিশেষে তারা সীমিত হয় তাদের সামগ্রীতে বর্তমানে কোনও অক্ষর রয়েছে $IFS। এই আচরণটি ডিফল্টরূপে সেট করা থাকে - তবে এটি অন্যথায় খুব সহজেই কনফিগার করা হয়।

set -f

এটি শেলকে গ্লোব না করার নির্দেশ দেয় । অন্ততপক্ষে সেটিংটি কোনওভাবে পূর্বাবস্থায় না ফেলা না হওয়া অবধি পথের নাম প্রসার ঘটবে না - যেমন যদি বর্তমান শেলটি অন্য নতুন শেল প্রক্রিয়া দ্বারা প্রতিস্থাপন করা হয় বা ....

set +f

... শেল জারি করা হয়। ডাবল-কোটস - যেমন তারা $IFS ক্ষেত্র-বিভাজনের জন্যও করে - এই বিশ্বব্যাপী সেটিংকে প্রসারণ ব্যতীত অপ্রয়োজনীয় রেন্ডার করে। তাই:

echo "*" *

... যদি পাঠের নামটি প্রসারণ করা সক্ষম করা হয় তবে সম্ভবত যুক্তি অনুসারে খুব আলাদা ফলাফল পাওয়া যাবে - কারণ প্রথমটি কেবল তার আক্ষরিক মানকেই প্রসারিত করবে (একক নক্ষত্রের অক্ষর, যা বলা হয় না, একেবারেই নয়) এবং দ্বিতীয়টি কেবল একই হয় যদি বর্তমান ওয়ার্কিং ডিরেক্টরিতে কোনও ফাইলের নাম নেই যা মিলতে পারে (এবং এটি প্রায় সকলের সাথে মেলে ) । তবে আপনি যদি:

set -f; echo "*" *

... উভয় যুক্তির ফলাফল একই রকম - *সেই ক্ষেত্রে এর প্রসারণ হয় না।


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

1
@ উইল্ডকার্ড - এটি একটি ক্ষেত্রের ডিলিমিটার। যদি আপনার কোনও ভেরিয়েবলের মান থাকে যা আপনি একাধিক ক্ষেত্রগুলিতে প্রসারিত করতে চান তবে আপনি এটি বিভক্ত করুন $IFScd /usr/bin; set -f; IFS=/; for path_component in $PWD; do echo $path_component; doneকপি করে প্রিন্ট \nতারপর usr\nতারপর bin\n। প্রথমটি echoখালি কারণ /একটি নাল ক্ষেত্র। পাথ_গমনকারীদের নতুন লাইন বা স্পেস থাকতে পারে বা যাই হোক না কেন - উপাদানগুলি বিভক্ত হয়ে গেছে /এবং না ডিফল্ট মান হিসাবে would লোকেরা awkযে কোনও উপায়ে / সর্বদা এটি করে। আপনার শেল এটিও করে
মাইক্রজারভ

3

আমার কাছে একটি বড় ভিডিও প্রকল্প ছিল যাতে ফাইলের নাম এবং ডিরেক্টরিতে ফাঁকা স্থান রয়েছে। find -type f -print0 | xargs -0বিভিন্ন উদ্দেশ্যে এবং বিভিন্ন শেল জুড়ে কাজ করার সময় , আমি দেখতে পেয়েছি যে আপনি বাশ ব্যবহার করছেন যদি একটি কাস্টম আইএফএস (ইনপুট ফিল্ড বিভাজক) ব্যবহার করা আপনাকে আরও নমনীয়তা দেয়। নীচের স্নিপেটটি ব্যাশ ব্যবহার করে এবং আইএফএসকে কেবল একটি নতুন লাইনে সেট করে; আপনার ফাইলের নামগুলিতে নিউলাইনগুলি না থাকলে শর্ত থাকে:

(IFS=$'\n'; for i in $(find -type f -print) ; do
    echo ">>>$i<<<"
done)

আইএফএসের পুনঃনির্ধারণকে আলাদা করতে পেরেনের ব্যবহারটি নোট করুন। আমি কীভাবে আইএফএস পুনরুদ্ধার করব সে সম্পর্কে অন্যান্য পোস্টগুলি পড়েছি তবে এটি কেবল সহজ।

আরও, আইএফএসকে নতুন লাইনে সেট করা আপনাকে শেল ভেরিয়েবলগুলি আগেই সেট করতে দেয় এবং সেগুলি সহজে মুদ্রণ করে। উদাহরণস্বরূপ, আমি বিভাজক হিসাবে নিউলাইনগুলি ব্যবহার করে ক্রমবর্ধমান ভেরিয়েবল বৃদ্ধি করতে পারি:

V=""
V="./Ralphie's Camcorder/STREAM/00123.MTS,04:58,05:52,-vf yadif"
V="$V"$'\n'"./Ralphie's Camcorder/STREAM/00111.MTS,00:00,59:59,-vf yadif"
V="$V"$'\n'"next item goes here..."

এবং অনুরূপ:

(IFS=$'\n'; for v in $V ; do
    echo ">>>$v<<<"
done)

এখন আমি echo "$V"নতুন লাইনগুলি আউটপুট দেওয়ার জন্য ডাবল উদ্ধৃতি ব্যবহার করে ভি এর সেটিংটিকে "তালিকা" করতে পারি । ( ব্যাখ্যাটির জন্য এই থ্রেডে ক্রেডিট $'\n')


3
তবে তারপরেও আপনার কাছে নতুন লাইন বা গ্লোব অক্ষরযুক্ত ফাইলের নামগুলির সাথে সমস্যা হবে। আরও দেখুন: কেন অনুসন্ধানের আউটপুট খারাপ অভ্যাসটি ফাঁপা করছে? । যদি ব্যবহার করে থাকেন তবে আপনি ব্যবহার zshকরতে পারেন IFS=$'\0'এবং ব্যবহার করতে পারেন -print0( zshবিস্তৃতিতে গ্লোব্বিং করবেন না যাতে গ্লোব অক্ষরগুলি সেখানে সমস্যা না হয়)।
স্টাফেন চেজেলাস

1
এটি শূন্যস্থান সম্বলিত ফাইলের নামের সাথে কাজ করে, তবে এটি সম্ভাব্য প্রতিকূল ফাইলের নাম বা দুর্ঘটনাজনিত "অযৌক্তিক" ফাইলের নামের বিরুদ্ধে কাজ করে না। ওয়াইল্ডকার্ড অক্ষর যুক্ত ফাইলের নামগুলি আপনি সহজেই যুক্ত করে ঠিক করতে পারেন set -f। অন্যদিকে, আপনার পদ্ধতির মধ্যে নিউলাইনগুলি থাকা ফাইলের নামগুলি মৌলিকভাবে ব্যর্থ হয়। ফাইলের নাম বাদে অন্য ডেটার সাথে কাজ করার সময় এটি খালি আইটেমগুলির সাথেও ব্যর্থ হয়।
গিলস

ঠিক আছে, আমার সতর্কতাটি হ'ল এটি ফাইলের নতুন লাইনের সাথে কাজ করবে না। যাইহোক, আমি বিশ্বাস করি আমাদের কেবল উন্মাদনার লাজুক লাইনটি আঁকতে হবে ;-)
রাশ

এবং কেন নিশ্চিত যে এটি কেন ডাউনটা পেয়েছে not স্পেস সহ ফাইলের নামগুলি দিয়ে পুনরাবৃত্তি করার জন্য এটি একটি উপযুক্ত যুক্তিযুক্ত পদ্ধতি। -প্রিন্ট0 ব্যবহারের জন্য xargs প্রয়োজন এবং এমন কিছু জিনিস রয়েছে যা সেই চেইনটি ব্যবহার করা কঠিন। আমি দুঃখিত যে কেউ আমার উত্তরের সাথে একমত নয়, তবে এটি এটিকে নিম্নমানের করার কোনও কারণ নেই।
রাশ

0

উপরে উল্লিখিত সমস্ত সুরক্ষা বিষয়বস্তু বিবেচনা করে এবং ধরে নিই যে আপনার বিশ্বাস এবং আপনার প্রসারিত ভেরিয়েবলগুলির উপর নিয়ন্ত্রণ রয়েছে এটি ব্যবহার করে হোয়াইটস্পেস ব্যবহার করে একাধিক পাথের ব্যবহার সম্ভব eval। কিন্তু সতর্কতা অবলম্বন করা আবশ্যক!

$ FILES='"a b" c'
$ eval ls $FILES
ls: a b: No such file or directory
ls: c: No such file or directory
$ FILES='a\ b c'
$ eval ls $FILES
ls: a b: No such file or directory
ls: c: No such file or directory
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.