যুক্তি হিসাবে খুঁজে পাওয়া ফাইলগুলি কীভাবে পাস করবেন?


9

কাটা তুচ্ছ কিন্তু বেমানান উত্তর বন্ধ করতে প্রথম: আমি তন্ন তন্ন ব্যবহার করতে পারেন find+ + xargsকৌতুক না এর রূপগুলো (যেমন findসঙ্গে -exec) কারণ আমি কলের জন্য প্রতি কয়েক ধরনের এক্সপ্রেশন ব্যবহার করতে হবে। আমি এই শেষে ফিরে পাবেন।


এখন আরও একটি ভাল উদাহরণের জন্য বিবেচনা করা যাক:

$ find -L some/dir -name \*.abc | sort
some/dir/1.abc
some/dir/2.abc
some/dir/a space.abc

আমি কীভাবে এগুলিকে যুক্তি হিসাবে পাস করব program?

কেবল এটি করা কৌশলটি করে না

$ ./program $(find -L some/dir -name \*.abc | sort)

programনিম্নলিখিত যুক্তি পাওয়ার পরে ব্যর্থ :

[0]: ./program
[1]: some/dir/1.abc
[2]: some/dir/2.abc
[3]: some/dir/a
[4]: space.abc

যেমন দেখা যায়, স্থান সহ পথটি বিভক্ত ছিল এবং programএটিকে দুটি পৃথক যুক্তি হিসাবে বিবেচনা করে।

এটি কাজ না হওয়া পর্যন্ত উদ্ধৃতি

মনে হয় আমার মতো নবজাতক ব্যবহারকারীরা যখন এ জাতীয় সমস্যার মুখোমুখি হন, অবশেষে এটি কাজ না করা পর্যন্ত এলোমেলোভাবে উদ্ধৃতি যুক্ত করার ঝোঁক থাকে - কেবল এখানে এটি সাহায্য করবে বলে মনে হয় না…

"$(…)"

$ ./program "$(find -L some/dir -name \*.abc | sort)"
[0]: ./program
[1]: some/dir/1.abc
some/dir/2.abc
some/dir/a space.abc

যেহেতু উদ্ধৃতিগুলি শব্দ বিভাজন প্রতিরোধ করে, সমস্ত ফাইল একক যুক্তি হিসাবে পাস করা হয়েছে।

পৃথক পথ উদ্ধৃত করা

একটি প্রতিশ্রুতিবদ্ধ পদ্ধতির:

$ ./program $(find -L some/dir -name \*.abc -printf '"%p"\n' | sort)
[1]: "some/dir/1.abc"
[2]: "some/dir/2.abc"
[3]: "some/dir/a
[4]: space.abc"

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

আইএফএস পরিবর্তন করুন

তারপরে আমি চারপাশে খেলার চেষ্টা করেছি IFS। আমি পছন্দ করেন findসঙ্গে -print0এবং sortসঙ্গে -zযাহাই হউক না কেন - তাই যে তারা "ওয়্যার্ড পাথ" নিজেদের কোন সমস্যা থাকবে না। তাহলে কেন শব্দটিকে nullচরিত্রের উপর বিভাজন করতে বাধ্য করা এবং সব কিছু নেই?

$ ./program $(IFS=$'\0' find -L some/dir -name \*.abc -print0 | sort -z)
[0]: ./program
[1]: some/dir/1.abcsome/dir/2.abcsome/dir/a
[2]: space.abc

সুতরাং এটি এখনও স্পেসে বিভক্ত হয় এবং বিভক্ত হয় না null

আমি IFSঅ্যাসাইনমেন্টটি উভয় $(…)(উপরে দেখানো হিসাবে) এবং আগে রাখার চেষ্টা করেছি ./program। এছাড়াও আমি অন্য সিনট্যাক্স চেষ্টা মত \0, \x0, \x00উভয় সঙ্গে উদ্ধৃত 'এবং "সঙ্গে ছাড়া সেইসাথে $। এগুলির মধ্যে কোনওরকমই কোনও পার্থক্য মনে হয়নি ...


এবং এখানে আমি ধারণার বাইরে। আমি আরও কয়েকটি জিনিস চেষ্টা করেছিলাম তবে সমস্তগুলি তালিকাভুক্ত একই সমস্যাগুলিতে ডুবে গেছে বলে মনে হচ্ছে।

আমি আর কি করতে পারি? এটা আদৌ কি doable?

অবশ্যই, আমি programনিদর্শনগুলি গ্রহণ করতে পারি এবং নিজে অনুসন্ধান করতে পারি। এটি নির্দিষ্ট সিনট্যাক্সে ফিক্স করার সময় এটি অনেকগুলি দ্বিগুণ কাজ। ( grepউদাহরণস্বরূপ ফাইল সরবরাহের বিষয়ে কী ?)।

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


শেষে, আমি আপনাকে আবার স্মরণ করিয়ে দিই যে find+ xargs(এবং একই ধরণের) কৌশলগুলি আমার ক্ষেত্রে কার্যকর হবে না। বর্ণনা সরলতার জন্য আমি কেবল একটি যুক্তি প্রদর্শন করছি। তবে আমার আসল কেসটি আরও দেখতে এরকম দেখাচ্ছে:

$ ABC_FILES=$(find -L some/dir -name \*.abc | sort)
$ XYZ_FILES=$(find -L other/dir -name \*.xyz | sort)
$ ./program --abc-files $ABC_FILES --xyz-files $XYZ_FILES

সুতরাং একটি xargsঅনুসন্ধান থেকে একটি করা এখনও আমাকে কীভাবে অন্যটির সাথে ডিল করতে হবে তা ছেড়ে দেয় ...

উত্তর:


13

অ্যারে ব্যবহার করুন।

আপনার যদি নিজের ফাইলনামগুলিতে নতুন লাইনের সম্ভাবনাটি পরিচালনা করার প্রয়োজন না হয় তবে আপনি তা থেকে দূরে সরে যেতে পারেন

mapfile -t ABC_FILES < <(find -L some/dir -name \*.abc | sort)
mapfile -t XYZ_FILES < <(find -L other/dir -name \*.xyz | sort)

তারপর

./program --abc-files "${ABC_FILES[@]}" --xyz-files "${XYZ_FILES[@]}"

আপনি যদি না ফাইলের নামের মধ্যে হাতল নতুন লাইন করতে হবে, এবং ব্যাশ> = 4.4, আপনি ব্যবহার করতে পারেন আছে -print0এবং -d ''নাল-বিনষ্ট অ্যারের নির্মানের সময় নাম:

mapfile -td '' ABC_FILES < <(find -L some/dir -name \*.abc -print0 | sort -z)

(এবং একইভাবে এর জন্য XYZ_FILES)। আপনার কাছে যদি নতুন বাশ না থাকে তবে আপনি অ্যারেতে ফাইলের নাম যুক্ত করতে একটি নাল-টার্মিনেটেড রিড লুপ ব্যবহার করতে পারেন যেমন

ABC_FILES=()
while IFS= read -rd '' f; do ABC_FILES+=( "$f" ); done < <(find -L some/dir -name \*.abc -print0 | sort -z)

অসাধারণ! আমি অ্যারে সম্পর্কে চিন্তা ছিল। তবে কোনওভাবেই আমি mapfileএটিতে (বা এর প্রতিশব্দ readarray) কিছুই পাইনি । কিন্তু এটি কাজ করে!
আদম বদুরা

তবুও আপনি এটি কিছুটা উন্নতি করতে পারেন। whileলুপের সাথে ব্যাশ <৪.৪ সংস্করণ (যা আমি হব ...) অ্যারে সাফ করে না। যার অর্থ হ'ল যদি কোনও ফাইল পাওয়া না যায় তবে অ্যারেটি সংজ্ঞায়িত। যদিও এটি ইতিমধ্যে সংজ্ঞায়িত হলে নতুন ফাইল যুক্ত করা হবে (পুরানো ফাইলগুলি প্রতিস্থাপনের পরিবর্তে)। দেখে মনে হচ্ছে এর declare -a ABC_FILES='()';আগে যোগ করা whileকৌশলটি করে। (কেবল যোগ করার পরে ABC_FILES='()';না))
অ্যাডাম বদুরা

এছাড়াও < <এখানে মানে কি ? এটি কি হিসাবে একই <<? আমি এটিকে <<সিনট্যাক্স ত্রুটির ("অপ্রত্যাশিত টোকেন` ('")) হিসাবে পরিবর্তন করার মত মনে করি না So তবে এটি কী এবং এটি কীভাবে কাজ করে?
অ্যাডাম বদুরা

আরেকটি উন্নতি (আমার নির্দিষ্ট ব্যবহারের সাথে সাথে) আরও একটি অ্যারে তৈরি করা। সুতরাং আমরা যারা আছে ABC_FILES। ওটা দারুন. তবে এটি ABS_ARGSফাঁকা অ্যারে যা খালি থাকলে তা তৈরি করা দরকারী ABC_FILESবা অন্যথায় এটি অ্যারে ('--abc-files' "${ABC_FILES[@]}")। এইভাবে পরে আমি এটি এটির মতো ব্যবহার করতে পারি: ./program "${ABC_ARGS[@]}" "${XYZ_ARGS[@]}"এবং নিশ্চিত হয়ে থাকুন যে গ্রুপগুলির কোনও (যদি থাকে) খালি থাকুক না কেন এটি সঠিকভাবে কাজ করবে। বা এটিকে অন্যভাবে বর্ণনা করতে: এই উপায়টি --abc-files(এবং --xyz-files) কেবলমাত্র কোনও বাস্তব পথ অনুসরণ করলেই সরবরাহ করা হবে।
আদম বদুরা

1
@AdamBadura: while read ... done < <(find blah)স্বাভাবিক শেল ফেরৎ হয় <দ্বারা নির্মিত একটি বিশেষ ফাইল থেকে প্রক্রিয়া প্রতিকল্পন । এটি পাইপিংয়ের থেকে পৃথক find blah | while read ... doneকারণ পাইপলাইনটি whileসাবশেলে লুপটি চালায় সুতরাং এতে বর্ণ (গুলি) পরবর্তী কমান্ডগুলির জন্য রক্ষা করা হবে না।
dave_thompson_085

3

আপনি আইএফএস = নিউলাইন ব্যবহার করতে পারেন (কোনও ফাইলনামে নতুন লাইন থাকে না ধরে নেওয়া) তবে আপনাকে অবশ্যই বিকল্পের আগে এটি অবশ্যই বাইরের শেলের মধ্যে সেট করতে হবে:

$ ls -1
a file with spaces
able
alpha
baker
boo hoo hoo
bravo
$ # note semicolon here; it's not enough to be in the environment passed
$ # to printf, it must be in the environment OF THE SHELL WHILE PARSING
$ IFS=$'\n'; printf '%s\n' --afiles $(find . -name 'a*') --bfiles $(find . -name 'b*')
--afiles
./able
./a file with spaces
./alpha
--bfiles
./bravo
./boo hoo hoo
./baker

সঙ্গে zshকিন্তু bashআপনি নাল ব্যবহার করতে পারেন $'\0'পাশাপাশি। এমনকি আপনি bashযদি নিউলাইন হ্যান্ডেল করতে পারেন তবে যদি এমন একটি যথেষ্ট অদ্ভুত চরিত্র থাকে যা কখনও কখনও ব্যবহার করা হয় না

 IFS=$'\1'; ... $(find ... -print0 | tr '\0' '\1') ...

যাইহোক, এই স্টাফটি @ স্টিল্ড্রাইভারের মন্তব্যে আপনি যে অতিরিক্ত অনুরোধ করেছেন তাতে কোনও শূন্য খুঁজে পাওয়া যায় না - - ফাইলগুলি বাদ দিতে জবাবদিহি করতে পারেন না।


সুতরাং আমি যেমন বুঝেছি তেমন কোন উপায় নেই IFSযে বিভক্ত হওয়ার জন্য null?
আদম বদুরা

@ অ্যাডামবাডুরা: আমি নিশ্চিত নই; আইএফএস সহ কোনও চলকটিতে বাশ নাল বাইটের অনুমতি দেয় না। নোট করুন যে read -d ''স্টিল্ড্রাইভারের পদ্ধতিগুলিতে ব্যবহৃত হ'ল একটি খালি স্ট্রিং যা নাল বাইটযুক্ত নয়। (এবং কোনও আদেশের বিকল্পটি যেমন কোনও
রূপের

এছাড়াও আপনি নিষ্ক্রিয় globbing (অবশ্যই set -o noglob(ইন ছাড়া বিভক্ত + + উল্লিখিত glob অপারেটর ব্যবহার করার পূর্বে) zsh)।
স্টাফেন চেজেলাস


@ অ্যাডামবাডুরা হ্যাঁ, ব্যাশে, একটি নাল হুবহু একই রকম $'\0'এবং একইভাবে ''
আইজাক

1

আপনি কেন হাল ছেড়ে দিয়েছেন তা আমি নিশ্চিত বুঝতে পারছি না xargs

সুতরাং একটি xargsঅনুসন্ধান থেকে একটি করা এখনও আমাকে কীভাবে অন্যটির সাথে ডিল করতে হবে তা ছেড়ে দেয় ...

স্ট্রিংটি --xyz-filesঅনেকগুলি আর্গুমেন্টগুলির মধ্যে একটি এবং এটি আপনার প্রোগ্রাম দ্বারা ব্যাখ্যা করার আগে এটি বিশেষ বিবেচনা করার কোনও কারণ নেই। আমি মনে করি আপনি এটি xargsউভয় findফলাফলের মধ্যে দিয়ে যেতে পারেন :

{ find -L some/dir -name \*.abc -print0 | sort -z; echo -ne "--xyz-files\0"; find -L other/dir -name \*.xyz -print0 | sort -z; } | xargs -0 ./program --abc-files

তুমি ঠিক! এটি পাশাপাশি কাজ করে! তবে লক্ষ্য করুন যে আপনি -print0দ্বিতীয় থেকে মিস করেছেন find। এছাড়াও এই উপায় যাচ্ছে যদি আমি করা হবে --abc-filesএকটি হিসাবে echoহিসাবে ভাল - শুধু দৃঢ়তা জন্য।
আদম বদুরা 25:58

এই পদ্ধতিরটিকে অ্যারে পদ্ধতির চেয়ে সহজ এবং কিছুটা বেশি লাইন লাগছে। তবে কেস কভার করার জন্য এটি কিছু অতিরিক্ত যুক্তি প্রয়োজন যে যদি কোনও .abcফাইল না থাকে তবে সেখানে কোনও --abc-files(একই সাথে .xyz) থাকা উচিত নয়। অ্যারে-ভিত্তিক সমাধান দ্বারা steeldriver এটি জন্য অতিরিক্ত যুক্তিবিজ্ঞান প্রয়োজন কিন্তু যখন তা এখানে না তাই তুচ্ছ হতে পারে এই সমাধান প্রধান সুবিধা অন্তক যে যুক্তি সেখানে তুচ্ছ হয় - সরলতা।
আদম বদুরা

এছাড়াও আমি সত্যিই নিশ্চিত নই কিন্তু আমি অনুমান xargsআর্গুমেন্ট বিভক্ত এবং এক পরিবর্তে কয়েক কমান্ড করতে, চেষ্টা করব না যদি না এটা হয় স্পষ্টভাবে তাই না করার নির্দেশ -L, --max-lines( -l), --max-args( -n) অথবা --max-chars( -s) আর্গুমেন্ট। আমি কি সঠিক? নাকি কিছু খেলাপি আছে? যেহেতু আমার প্রোগ্রামটি এ জাতীয় বিভাজন সঠিকভাবে পরিচালনা করবে না এবং এটির কল করতে আমার ব্যর্থতা হবে ...
অ্যাডাম বদুরা

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

হ্যাঁ, আমি ইতিমধ্যে অ্যারে-ভিত্তিক সমাধানটি প্রয়োগ করেছি এবং এটি কবজির মতো কাজ করে। আমি বিশেষভাবে গর্বিত যে এটি কতটা পরিষ্কারভাবে বিকল্পের সাথে আচরণ করে (যদি ফাইল না থাকে তবে --abc-files)। তবে আপনি ঠিক বলেছেন - আপনার বিকল্পগুলি জানা ভাল! বিশেষত যে আমি ভুল করে ভেবেছিলাম এটি সম্ভব নয়।
আদম বদুরা
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.