স্টার্ডিন / স্টডআউট পুনঃনির্দেশ সহ xargs


21

আমি চালাতে চাই:

./a.out < x.dat > x.ans

প্রতিটি * জন্য .dat ডিরেক্টরির মধ্যে ফাইল একটি

অবশ্যই, এটি বাশ / পাইথন / যে কোনও স্ক্রিপ্ট দ্বারা করা যেতে পারে তবে আমি সেক্সি ওয়ান-লাইন লিখতে পছন্দ করি। আমি যা পৌঁছতে পারলাম তা হ'ল (এখনও কোনও স্টডআউট ছাড়াই):

ls A/*.dat | xargs -I file -a file ./a.out

কিন্তু -a xargs প্রতিস্থাপন কার্যক্রম 'ফাইল' বুঝে না।

সহায়তার জন্য আপনাকে ধন্যবাদ।


এখানে অন্যান্য ভাল উত্তরের পাশাপাশি আপনি জিএনইউ xargs -a বিকল্পটি ব্যবহার করতে পারেন।
জেমস ইয়ংম্যান

উত্তর:


30

প্রথমত, ফাইল তালিকা হিসাবে আউটপুট ব্যবহার করবেন নাls । শেল প্রসার বা ব্যবহার করুন findLs + xargs অপব্যবহারের সম্ভাব্য পরিণতি এবং সঠিক xargsব্যবহারের উদাহরণের জন্য নীচে দেখুন ।

1. সহজ উপায়: লুপ জন্য

আপনি যদি কেবল অধীনে থাকা ফাইলগুলি প্রক্রিয়া করতে চান A/তবে একটি সাধারণ forলুপ যথেষ্ট হওয়া উচিত:

for file in A/*.dat; do ./a.out < "$file" > "${file%.dat}.ans"; done

2. প্রাক 1 কেন না   ls | xargs ?

আপনি যদি কাজের lsসাথে xargsএটি ব্যবহার করেন তবে কীভাবে খারাপ জিনিসগুলি ঘুরে আসতে পারে তার একটি উদাহরণ এখানে । নিম্নলিখিত পরিস্থিতিতে বিবেচনা করুন:

  • প্রথমে কিছু খালি ফাইল তৈরি করা যাক:

    $ touch A/mypreciousfile.dat\ with\ junk\ at\ the\ end.dat
    $ touch A/mypreciousfile.dat
    $ touch A/mypreciousfile.dat.ans
    
  • ফাইলগুলি দেখুন এবং সেগুলিতে কিছুই নেই:

    $ ls -1 A/
    mypreciousfile.dat
    mypreciousfile.dat with junk at the end.dat
    mypreciousfile.dat.ans
    
    $ cat A/*
    
  • ব্যবহার করে একটি যাদু কমান্ড চালান xargs:

    $ ls A/*.dat | xargs -I file sh -c "echo TRICKED > file.ans"
    
  • ফলাফল:

    $ cat A/mypreciousfile.dat
    TRICKED with junk at the end.dat.ans
    
    $ cat A/mypreciousfile.dat.ans
    TRICKED
    

উভয় ওপর দিয়েই লিখতে তাই আপনি শুধু পরিচালিত থাকেন mypreciousfile.datএবং mypreciousfile.dat.ans। যদি এই ফাইলগুলিতে কোনও সামগ্রী থাকে তবে তা মুছে ফেলা হবে।


২. ব্যবহার   xargs : সঠিক পদ্ধতিতে  find 

আপনি ব্যবহার পীড়াপীড়ি করতে চান তাহলে xargs, ব্যবহার -0(নাল-সমাপ্ত নাম):

find A/ -name "*.dat" -type f -print0 | xargs -0 -I file sh -c './a.out < "file" > "file.ans"'

দুটি বিষয় লক্ষ্য করুন:

  1. এইভাবে আপনি ফাইলগুলি তৈরি করে .dat.ansশেষ করবেন;
  2. এই ভঙ্গ করবে যদি কিছু ফাইলের নাম উদ্ধৃতি চিহ্ন রয়েছে ( ")।

উভয় ইস্যু শেল আবেদনের বিভিন্ন উপায়ে সমাধান করা যেতে পারে:

find A/ -name "*.dat" -type f -print0 | xargs -0 -L 1 bash -c './a.out < "$0" > "${0%dat}ans"'

৩. সবই এর মধ্যে সম্পন্ন হয়েছে find ... -exec

 find A/ -name "*.dat" -type f -exec sh -c './a.out < "{}" > "{}.ans"' \;

এটি আবার .dat.ansফাইল তৈরি করে এবং ফাইলের নাম থাকলে তা ভেঙে যায় "। এটির জন্য, bashএটি শুরু করার পদ্ধতিটি ব্যবহার করুন এবং পরিবর্তন করুন:

 find A/ -name "*.dat" -type f -exec bash -c './a.out < "$0" > "${0%dat}ans"' {} \;

Ls এর আউটপুট পার্স না করার জন্য উল্লেখ করার জন্য +1
রাহমু

2
অপশন 2 বিরতি ফাইলের নামের রয়েছে "যখন।
thiton

2
খুব ভাল কথা, ধন্যবাদ! আমি সেই অনুযায়ী আপডেট করব।
রোজিট্রিজেভিয়াচজ

আমি শুধু উল্লেখ চান, যে যদি zshশেল হিসাবে ব্যবহার করা হয় (এবং SH_WORD_SPLIT সেট না করা হয়), সব বাজে বিশেষ ক্ষেত্রে (সাদা স্পেস, "FILENAME ইত্যাদি) প্রয়োজন বিবেচনা করা তুচ্ছ। for file in A/*.dat; do ./a.out < $file > ${file%.dat}.ans ; doneসব ক্ষেত্রেই কাজ করে।
jofel

-1 কারণ আমি স্টিডিনের সাথে কীভাবে xargs করব তা নির্ধারণ করার চেষ্টা করছি এবং ফাইলগুলির সাথে আমার প্রশ্নের কোনও সম্পর্ক নেই find
মেহরদাদ

2

এই জাতীয় কিছু করার চেষ্টা করুন (আপনার ব্যবহৃত শেলের উপর নির্ভর করে সিনট্যাক্স কিছুটা আলাদা হতে পারে):

$ for i in $(find A/ -name \*.dat); do ./a.out < ${i} > ${i%.dat}.ans; done


যে কাজ করবে না। এটি স্টাফের মতো চালনা করার চেষ্টা করবে somefile.dat.datএবং সমস্ত আউটপুটকে একটি ফাইলে পুনর্নির্দেশ করবে।
রোজিট্রিজেভিয়াচজ

তুমি ঠিক বলছো. আমি এটিকে সংশোধন করার জন্য সমাধানটি সম্পাদনা করেছি।
রাহমু

ঠিক আছে - প্রায় ভাল :) কেবল somefile.dat.ansআউটপুট স্টাফগুলি দেখতে এত সুন্দর লাগবে না।
rozcietrzewiacz

1
সম্পাদিত! আমি '%' সম্পর্কে জানতাম না। টিপটির জন্য ধন্যবাদ, এটি একটি কবজির মতো কাজ করে।
রাহমু

1
একটি যোগ -type fileকরা ভাল (না পারে < directory), এবং এটি অস্বাভাবিক ফাইল-নাম পরী দু: খিত করে তোলে।
মাদুর

2

সাধারণ নিদর্শনগুলির জন্য, লুপের জন্য উপযুক্ত:

for file in A/*.dat; do
    ./a.out < "${file}" > "${file%.dat}.ans" # Never forget the QUOTES!
done

আরও জটিল ক্ষেত্রে যেখানে আপনার ফাইলগুলি তালিকাভুক্ত করার জন্য আরেকটি ইউটিলিটি প্রয়োজন (zsh বা ব্যাশ 4 এর শক্তিশালী যথেষ্ট নিদর্শন রয়েছে যা আপনার খুব কমই খুঁজে পাওয়া দরকার তবে আপনি যদি পসিক্স শেলের মধ্যেই থাকতে চান বা দ্রুত শেল ড্যাশের মতো ব্যবহার করতে চান তবে আপনাকে কোনও কিছুর সন্ধান করতে হবে অ-তুচ্ছ), পড়ার সময় সবচেয়ে উপযুক্ত:

find A -name '*.dat' -print | while IFS= read -r file; do
   ./a.out < "${file}" > "${file%.dat}.ans" # Never forget the QUOTES!
done

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


2

জিএনইউ সমান্তরাল ব্যবহার করুন:

parallel ./a.out "<{} >{.}.ans" ::: A/*.dat

যুক্ত বোনাস: আপনি সমান্তরালভাবে প্রক্রিয়াজাতকরণ সম্পন্ন করুন।

আরও জানতে ইন্ট্রো ভিডিওগুলি দেখুন: http://www.youtube.com/watch?v=OpaiGYxkSuQ


1

আমি মনে করি xargs এ আপনার কমপক্ষে শেল ডাকা দরকার:

ls A/*.dat | xargs -I file sh -c "./a.out < file > file.ans"

সম্পাদনা: এটি লক্ষ্য করা উচিত যে যখন ফাইলের নামগুলিতে সাদা স্থান থাকে তখন এই পদ্ধতিটি কার্যকর হয় না। কাজ করতে পারে না। এমনকি যদি আপনি জার্গাগুলি স্পেসগুলি সঠিকভাবে বুঝতে তৈরি করতে -0 এবং xargs -0 ব্যবহার করেন, -c শেল কলটি তাদের উপর ক্র্যাক হবে। যাইহোক, ওপি স্পষ্টভাবে একটি xargs সমাধানের জন্য জিজ্ঞাসা করেছিল, এবং এটিই আমি নিয়ে এসেছি সেরা xargs সমাধান। যদি ফাইলের নামগুলিতে হোয়াইটস্পেস কোনও সমস্যা হতে পারে তবে ফাইন্ড-এক্সেক বা শেল লুপ ব্যবহার করুন।



@ ক্রোয়েট্রিজেভিয়াক্জ: সাধারণভাবে, নিশ্চিত, তবে আমি ধরে নিই যে কেউ কেউ জার্গজ ভুডু করার চেষ্টা করছেন এটি এটি জানেন। যেহেতু এই ফাইলের নামগুলি অন্য শেল সম্প্রসারণের মধ্য দিয়ে চলেছে, সেগুলি যাইহোক ভাল আচরণ করতে হবে।
thiton

1
শেল প্রসারণ সম্পর্কে আপনি ভুল। lsফাঁকা স্থান ছাড়াই জিনিস ছাড়িয়ে যায় এবং এটাই সমস্যা।
রোজিট্রিজেভিয়াচজ

@ ক্রোয়েট্রিজেভিয়াক্জ: হ্যাঁ, আমি সেই সমস্যাটি বুঝতে পারি। এখন কেবল ধরুন আপনি সঠিকভাবে এই স্পেসগুলি ছেড়ে পালাতে পারবেন এবং এগুলি xargs এ পাবেন: সেগুলি sh এর -c স্ট্রিংয়ে প্রতিস্থাপন করা হবে, sh -c স্ট্রিংকে টোকেনাইজ করে, এবং সমস্ত কিছু বিরতি।
thiton

হ্যাঁ। আপনি এখন দেখুন, পার্সিং lsভাল হয় না। তবে সন্ধানের সাথে নিরাপদে ব্যবহার করা xargs যেতে পারে - আমার উত্তর 2 নং পরামর্শ দেখুন।
রোজিট্রিজেভিয়াজz

1

এটি জটিল করার দরকার নেই। আপনি এটি একটি forলুপ দিয়ে করতে পারেন :

for file in A/*.dat; do
  ./a.out < "$file" >"${file%.dat}.ans"
done

${file%.dat}.ansবিট সরাবে .datমধ্যে ফাইলের নাম থেকে ফাইলের নাম প্রত্যয় $fileএবং এর পরিবর্তে যোগ .ansশেষ।

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