"Xargs গ্রেপ" কি করে?


25

আমি grepকমান্ডটি জানি এবং আমি এর কার্যকারিতা সম্পর্কে শিখছি xargs, সুতরাং আমি এই পৃষ্ঠাটি পড়েছি যা xargsকমান্ডটি কীভাবে ব্যবহার করতে হয় তার কয়েকটি উদাহরণ দেয় ।

আমি শেষ উদাহরণটি, উদাহরণস্বরূপ 10 দ্বারা বিভ্রান্ত হয়ে পড়েছি। এতে বলা হয়েছে "xargs কমান্ড গ্রেড কমান্ড কার্যকর করে সমস্ত ফাইল (ফাইন্ড কমান্ড দ্বারা সরবরাহিত ফাইলগুলির মধ্যে) সন্ধান করার জন্য গ্রেড কমান্ড কার্যকর করে যা" stdlib.h '"স্ট্রিং রয়েছে।"

$ find . -name '*.c' | xargs grep 'stdlib.h'
./tgsthreads.c:#include
./valgrind.c:#include
./direntry.c:#include
./xvirus.c:#include
./temp.c:#include
...
...
...

তবে সহজভাবে ব্যবহার করতে পার্থক্য কী

$ find . -name '*.c' | grep 'stdlib.h'

?

স্পষ্টতই, আমি এখনও xargs যা করছে তা নিয়ে লড়াই করছি, সুতরাং যে কোনও সহায়তা প্রশংসিত!


2
এই প্রশ্নটি সহায়ক হতে পারে: XArgs কখন প্রয়োজন হয়?
TheOdd

উত্তর:


30
$ find . -name '*.c' | grep 'stdlib.h'

এটি আউটপুট (stdout) * থেকে find(স্টিডিন) * grep 'stdlib.h' পাঠ্য হিসাবে পাইপ দেয় (যেমন ফাইলের নামগুলি পাঠ্য হিসাবে বিবেচিত হয়)। grepএটি তার স্বাভাবিক কাজটি করে এবং এই পাঠ্যে মেলা লাইনগুলি খুঁজে পায় (যে কোনও ফাইলের নাম যা সেগুলি প্যাটার্ন ধারণ করে)। ফাইলগুলির বিষয়বস্তু কখনই পড়া হয় না।

$ find . -name '*.c' | xargs grep 'stdlib.h'

এই নির্মান কমান্ড grep 'stdlib.h' যা থেকে প্রতিটি ফলাফল findএকটি আর্গুমেন্ট হয় - তাই এই মিলের জন্য দেখবে ভিতরে প্রতিটি ফাইল পাওয়া দ্বারা find( xargsপ্রদত্ত কমান্ড আর্গুমেন্ট মধ্যে নিজের stdin বাঁক যেমন ভাবা যেতে পারে) *

-type fআপনার ফাইন্ড কমান্ডটি ব্যবহার করুন বা grepডিরেক্টরিগুলির সাথে মিল রেখে আপনি ত্রুটি পাবেন । এছাড়াও, যদি ফাইলনামগুলির স্পেস থাকে তবে এটি xargsখারাপভাবে স্ক্রু করবে, সুতরাং যুক্ত করে -print0এবং xargs -0আরও নির্ভরযোগ্য ফলাফলের জন্য নাল বিভাজকটি ব্যবহার করুন :

find . -type f -name '*.c' -print0 | xargs -0 grep 'stdlib.h'

* ক্যাট দ্বারা মন্তব্যে প্রস্তাবিত এই অতিরিক্ত ব্যাখ্যামূলক পয়েন্টগুলি যুক্ত করেছে


2
আপনি লক্ষ্য করার বিষয়টি বিবেচনা করতে পারেন (কারণ এটি আপনার বাদ পড়ে বলে মনে হচ্ছে) যে মূল পয়েন্টটি |পাইপগুলি গ্রেপের স্টিডিনে স্টডআউট করে যা গ্রেপের আর্গুমেন্টের মতো নয় এবং বিভ্রান্তিকর ফলাফল দেয়।
বিড়াল

1
অথবা জিএনইউ ফাইন্ডস ব্যবহার করুন find -name '*.c' -exec grep stdlib.h {} +। আমি বাস্তবে কখনও xargs ব্যবহার করি না। এছাড়াও বিস্মিত কেউই উল্লেখ করেনি যে জার্সগুলি grep $(find)প্রতিস্থাপনের আদেশের অনুরূপ উদ্দেশ্যে কাজ করে , তাই আমি আমার নিজের একটি উত্তর লিখেছিলাম। কম সীমাবদ্ধতা এবং সমস্যা সহ কমান্ড প্রতিস্থাপন হিসাবে xargs ব্যাখ্যা করা স্বাভাবিক বলে মনে হয়।
পিটার কর্ডস

আমি জার্গাগুলি ব্যবহার করার একটি পরিস্থিতি হ'ল যদি আমি ফলাফলের ফলে অনেকগুলি ফাইল মুছি। আপনি যদি কেবল এক্সেক্স আরএম করেন তবে এটি প্রতিটি ফাইলে একবারে আরএম চালাবে, যা খুব অদক্ষ। এক্সার্গসে পাইপিং করা সমস্ত একবারে একটি আরএম দিয়ে করবে। বলুন -n50 (একসাথে 50 করুন) দিয়ে সীমাবদ্ধ করা কমান্ড লাইন ওভারফ্লো (প্রচুর ফাইলের সমস্যা) রোধ করতে পারে।
lsd

1
@ এলএসডি: কেন find -deleteএই বিশেষ মামলার জন্য নয় ? অথবা rmআপনি যদি জিএনইউ খুঁজে পান তবে অন্য কমান্ডগুলির জন্য , তারপর -exec some_command {} +xargs এর মতো ব্যাচে বিভক্ত হন, পরিবর্তে \;প্রত্যেকটির জন্য পৃথক কমান্ড চালানোর আচরণ।
পিটার

@lsd findযদি এবং কেবল যদি এটা ব্যবহার করছে রান প্রতিটি ফাইল উপর আদেশ -exec command \;উভয় xargsএবং -exec command \+সিস্টেম দ্বারা অনুমোদিত আর্গুমেন্ট সর্বাধিক সংখ্যক ব্যক্তির সাথে কমান্ড কল হবে। অন্য কথায়, এগুলি সমতুল্য
সের্গেই কলডিয়াজহনি

6

xargs এর স্ট্যান্ডার্ড ইনপুট নেয় এবং এটিকে কমান্ড লাইন আর্গগুলিতে পরিণত করে।

find . -name '*.c' | xargs grep 'stdlib.h' খুব অনুরূপ

grep 'stdlib.h' $(find . -name '*.c')  # UNSAFE, DON'T USE

এবং ফাইলের নামগুলির তালিকা যতক্ষণ না একক কমান্ড লাইনের জন্য খুব বেশি দীর্ঘ না হয় ততক্ষণ একই ফলাফল দেবে। (লিনাক্স একক কমান্ড লাইনে মেগাবাইট পাঠ্য সমর্থন করে, তাই সাধারণত আপনার xargs প্রয়োজন হয় না))


তবে এই দুটিই স্তন্যপান করে, কারণ আপনার ফাইলের নামগুলিতে স্পেস থাকলে তা ভেঙে যায় । পরিবর্তে, find -print0 | xargs -0কাজ করে, কিন্তু তাই করে

find . -name '*.c' -exec grep 'stdlib.h' {} +

এটি ফাইলের নামগুলি কোথাও পাইপ দেয় না: findএগুলি একটি বড় কমান্ড লাইনে ব্যাচ করে এবং grepসরাসরি চলে।

\;পরিবর্তে +প্রতিটি ফাইলের জন্য পৃথকভাবে গ্রেপ রান করুন, যা অনেক ধীর। এটা করবেন না। তবে +এটি একটি জিএনইউ এক্সটেনশন, সুতরাং আপনি xargsযদি জিএনইউ অনুসন্ধান অনুমান করতে না পারেন তবে আপনাকে দক্ষতার সাথে এটি করা দরকার।


আপনি খুঁজে ছেড়ে যান তাহলে xargs, find | grepফাইলের নামের যে তালিকা বিরুদ্ধে প্যাটার্ন ম্যাচিং করে findকপি করে প্রিন্ট।

সুতরাং যে মুহুর্তে, আপনি পাশাপাশি করতে পারেন find -name stdlib.h। অবশ্যই, এর সাথে -name '*.c' -name stdlib.hআপনি কোনও আউটপুট পাবেন না কারণ এই নিদর্শনগুলি উভয়ই মেলে না।

lessপাইপলাইনের কোনও অংশ কী আউটপুট উত্পাদন করে তা প্রক্রিয়াটির যে কোনও বিন্দুতে বিকল্প করুন ।


আরও পঠন: http://mywiki.wooledge.org/ বাশএফএকিউতে কিছু দুর্দান্ত জিনিস রয়েছে।


1
জিএনইউ xargs- তে -dপৃথককারীও সেট করতে হবে, সুতরাং আপনি -d'\n'একটি নতুন লাইন-বিচ্ছিন্ন তালিকা পরিচালনা করতে পারবেন , যা আপনি যদি কোনও ফাইলের মধ্যে ফাইলের নামের তালিকা পরিচালনা করেন তবে দরকারী হতে পারে (যতক্ষণ না ফাইলের নাম না থাকে তাদের মধ্যে
নিউলাইনগুলি

@ ইল্কাচ্চু: হ্যাঁ, ফাইলের নামগুলিতে নিউলাইনগুলি স্থানগুলির চেয়ে অনেক বেশি বিরল, কারণ তারা বেশিরভাগ স্ক্রিপ্টগুলি ভাঙে। myfunc(){ local IFS=$'\n'; fgrep stdlib.h` find (সন্ধান করুন) ; }একই প্রভাব সহ কাজ করে। অথবা ওয়ান-লাইনার হিসাবে, একটি (IFS=...; cmd...)সাব - শেল এটি সংরক্ষণ / পুনরুদ্ধার না করে আইএফএসে পরিবর্তনটি নিয়ন্ত্রণ করতেও কাজ করে।
পিটার কর্ডস

@ পিটারকর্ডস দয়া করে command $( find )ধরণের জিনিস ব্যবহার করবেন না । স্পেস এবং বিশেষ অক্ষরগুলির সাথে সমস্যাযুক্ত ফাইলের নামগুলি এই ধরণের জিনিসটিকে ভেঙে দিতে পারে। খুব কম ডাবল উদ্ধৃতিতে কমান্ড প্রতিস্থাপন।
সের্গেই কোলোডিয়াজনি

@ সের্গি কলোডিএজনি: দেখানোর জন্য ধন্যবাদ যে দেখে মনে হচ্ছে যে আমি আসলে এটি করার পরামর্শ দিচ্ছি। স্কিমিং করা লোকেরা পরবর্তী বিভাগটি পড়ার পরিবর্তে এটি অনুলিপি / আটকানো থাকতে পারে। যে ঠিকানা আপডেট।
পিটার

@ সের্গি কলডিয়াজনি: নাকি আপনি আমার মন্তব্যে জবাব দিচ্ছেন? লক্ষ্য করুন যে আমি সেট করেছিলাম IFSএটি ব্যবহারের সমতুল্য xargs '-d\n'। কমান্ড প্রতিস্থাপনের প্রভাবগুলির আগে গ্লোব সম্প্রসারণ এবং শেল মেটাচার্যাক্টর প্রক্রিয়াজাতকরণ ঘটে, তাই আমি মনে করি এটি ফাইল নাম সহ $()বা থাকা ফাইলগুলির সাথেও নিরাপদ >। সম্মত হয়েছেন যে কমান্ড প্রতিস্থাপনে শব্দ-বিভাজন ব্যবহার করা এক-অফ ইন্টারেক্টিভ ব্যবহার ব্যতীত ভাল অনুশীলন নয় যেখানে আপনি ফাইলের নাম সম্পর্কে কিছু জানেন। তবে command "$(find)"কেবলমাত্র তখনই কার্যকর যদি আপনি এটি ঠিক 1 ফাইলের নাম উত্পাদন করে বলে আশা করেন ...
পিটার

5

সাধারণভাবে, xargsএমন ক্ষেত্রে ব্যবহৃত হয় যেখানে আপনি একটি চিহ্ন |থেকে অন্য কমান্ডের জন্য কিছু চিহ্ন (চিহ্ন সহ ) পাইপ করতেন Command1 | Command2, তবে প্রথম কমান্ড থেকে আউটপুট সঠিকভাবে দ্বিতীয় কমান্ডের ইনপুট হিসাবে গ্রহণ করা যায় না।

এটি সাধারণত ঘটে যখন স্ট্যান্ডার্ড ইন (স্টিডিন) এর মাধ্যমে দ্বিতীয় কমান্ড ডেটা ইনপুট সঠিকভাবে পরিচালনা করে না (উদাহরণস্বরূপ: একাধিক লাইন ইনপুট হিসাবে, লাইনগুলি যেভাবে সেটআপ হয়, অক্ষরগুলি ইনপুট হিসাবে ব্যবহৃত হয়, একাধিক পরামিতি ইনপুট হিসাবে ব্যবহৃত হয়, ডেটা টাইপ হিসাবে প্রাপ্ত হয়) ইনপুট, ইত্যাদি ..)। আপনাকে একটি দ্রুত উদাহরণ দেওয়ার জন্য, নিম্নলিখিতটি পরীক্ষা করুন:

উদাহরণ 1:

ls | echo- এটি echoকীভাবে কাজ করবে না যেহেতু তিনি যে ইনপুটটি গ্রহণ করছেন তা কীভাবে পরিচালনা করবেন তা জানেন না। এখন এই ক্ষেত্রে যদি আমরা xargsএটি ব্যবহার করি তবে ইনপুটটি এমনভাবে প্রক্রিয়া করা হবে যা সঠিকভাবে পরিচালনা করা যায় echo(উদাহরণস্বরূপ: তথ্যের একক লাইন হিসাবে)

ls | xargs echo- এটি lsএকক লাইনে সমস্ত তথ্য আউটপুট দেবে

উদাহরণ 2:

ধরা যাক আমার কাছে Go নামক ফোল্ডারের ভিতরে একাধিক GoLang ফাইল রয়েছে। আমি তাদের জন্য এই জাতীয় কিছু সন্ধান করব:

find go -name *.go -type f | echo- তবে যদি সেখানে পাইপ চিহ্ন এবং echoশেষে থাকে তবে এটি কার্যকর হবে না।

find go -name *.go -type f | xargs echo- এখানে এটি ধন্যবাদ জানায় xargsতবে আমি যদি findএকক লাইনে কমান্ডের কাছ থেকে প্রতিটি প্রতিক্রিয়া চাইতাম তবে আমি নিম্নলিখিতটি করতাম:

find go -name *.go -type f | xargs -0 echo- এই ক্ষেত্রে, একই আউটপুট findদ্বারা প্রদর্শিত হবে echo

কমান্ডগুলি পছন্দ করে cp, echo, rm, lessএবং অন্যান্য যেগুলি ইনপুট হ্যান্ডেল করার জন্য আরও ভাল পদ্ধতির প্রয়োজন হয় তা ব্যবহার করার সাথে সাথে একটি সুবিধা পান xargs


4

xargs ফাইলের তালিকার উপর ভিত্তি করে (সাধারণত) কমান্ড লাইন আর্গুমেন্ট স্বয়ংক্রিয়ভাবে তৈরি করতে ব্যবহৃত হয়।

সুতরাং অনুসরণকারী xargsকমান্ডটি ব্যবহারের কিছু বিকল্প বিবেচনা করুন :

find . -name '*.c' -print0 | xargs -0 grep 'stdlib.h'

অন্যান্য বিকল্পগুলির পরিবর্তে এটির ব্যবহারের বেশ কয়েকটি কারণ রয়েছে যা মূলত অন্যান্য উত্তরে উল্লেখ করা হয়নি:

  1. find . -name '*.c' -exec grep 'stdlib.h' {}\;grepপ্রতিটি ফাইলের জন্য একটি প্রক্রিয়া তৈরি করবে — এটিকে সাধারণত খারাপ অনুশীলন হিসাবে বিবেচনা করা হয় এবং অনেকগুলি ফাইল পাওয়া গেলে সিস্টেমে একটি বড় বোঝা চাপতে পারে।
  2. যদি অনেকগুলি ফাইল থাকে তবে একটি grep 'stdlib.h' $(find . -name '*.c')কমান্ড সম্ভবত ব্যর্থ হবে, কারণ $(...)অপারেশনের আউটপুট শেলটির সর্বাধিক কমান্ড লাইনের দৈর্ঘ্য ছাড়িয়ে যাবে

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

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