বাশ - আমি কি করতে পারি: সন্ধান করুন… এই && এর সাথে সন্ধান করুন?


23

যুক্তিযুক্তভাবে দুটি শেল কমান্ড সংযুক্ত করার উপায় আছে যা ফাইন্ড - এক্সিকিউট দিয়ে আহ্বান জানানো হয় ?

উদাহরণস্বরূপ , স্ট্রিং ফু সহ সমস্ত .csv ফাইল মুদ্রণ করার জন্য এর উপস্থিতিটি আমি করতে চাই:

find . -iname \*.csv -exec grep foo {} && echo {} \;

তবে বাশ "" এক্সেক "এর পক্ষে যুক্তি অনুপস্থিত" অভিযোগ করে


2
আপনি -execক্রমানুসারে 2 ব্যবহার করতে পারেন বা একটি একক ব্যবহার করতে পারেন -exec sh -c 'grep foo "$0" && printf %s\\n "$0"' {} \;
jw013

এটি আমাকে বারবার ছড়িয়ে দিয়েছে: আমি সর্বদা প্রত্যাশা করি যে প্রথম যুক্তিটি sh(এই ক্ষেত্রে {}) পাস হয়েছিল $1এবং এর $0মতো হবে sh। কিন্তু আসলে, আপনি সঠিক, প্রথম যুক্তি হিসাবে প্রদর্শিত হবে $0। প্রথম আর্গুমেন্টটি আমন্ত্রণকারী কমান্ডের নাম হ'ল একটি সম্মেলন, যা স্বয়ংক্রিয়ভাবে এই ক্ষেত্রে প্রয়োগ করা হয় না।
সন্দেহভাজন জিম

হতে পারে এই প্রশ্নের সাথে একত্রীকরণ করা উচিত: unix.stackexchange.com/q/18077/4801
dubiousjim

উত্তর:


24

-execহ'ল এমন একটি শিকারী যা কমান্ড চালায় (শেল নয়) এবং কমান্ডের ফলাফলের ভিত্তিতে সত্য বা মিথ্যা (শূন্য বা অ-শূন্য বহির্গমন স্থিতি) এর উপর ভিত্তি করে মূল্যায়ন করে ।

তাই:

find . -iname '*.csv' -exec grep foo {} \; -print

ফাইলের মধ্যে foo খুঁজে পেলে ফাইল পাথ মুদ্রণ করবে grep। আপনি পরিবর্তে -printঅন্য -execশিকারী বা অন্য কোনও শিকারী ব্যবহার করতে পারেন

find . -iname '*.csv' -exec grep foo {} \; -exec echo {} \;

আরও দেখুন !এবং -oঅস্বীকৃতি এবং জন্য অপারেটরদের খুঁজে অথবা

বিকল্পভাবে, আপনি এই হিসাবে একটি শেল শুরু করতে পারেন:

find . -iname '*.csv' -exec sh -c '
   grep foo "$1" && echo "$1"' sh {} \;

বা প্রতিটি ফাইলের জন্য শেল শুরু করা এড়াতে:

find . -iname '*.csv' -exec sh -c '
  for i do
    grep foo "$i" && echo "$i"
  done' sh {} +

10

আপনি যে সমস্যার মুখোমুখি হচ্ছেন তা হ'ল শেলটি প্রথমে কমান্ড লাইনটি পার্স করে এবং &&অপারেটর দ্বারা পৃথক করা দুটি সহজ কমান্ড দেখায়:, find . -iname \*.csv -exec grep foo {}এবং echo {} \;। বরাত দিয়ে &&( find . -iname \*.csv -exec grep foo {} '&&' echo {} \;) রোধ করা যাবে, কিন্তু এখন কমান্ড দ্বারা সঞ্চালিত findমত কিছু grepআর্গুমেন্ট সহ foo, wibble.csv, &&, echoএবং wibble.csv। আপনাকে findএকটি শেল চালানোর জন্য নির্দেশনা দিতে হবে যা &&অপারেটরের ব্যাখ্যা করবে :

find . -iname \*.csv -exec sh -c 'grep foo "$0" && echo "$0"' {} \;

লক্ষ্য করুন প্রথম আর্গুমেন্ট পরে sh -c SOMECOMMANDহয় $0, না $1

আপনি প্রতিটি ফাইলের জন্য শেল প্রক্রিয়া শুরু করার সময়টি কমান্ডের অনুরোধের সাথে গ্রুপবদ্ধ করে বাঁচাতে পারেন -exec … +। প্রসেসিংয়ের স্বাচ্ছন্দ্যের জন্য, কিছু ডামি মান পাস করুন $0যাতে "$@"ফাইলের নামগুলি গণনা করা হয়।

find . -iname \*.csv -exec sh -c 'for x in "$@"; do grep foo "$x" && echo "$x"; done' \ {} +

শেল কমান্ড মাত্র দুই প্রোগ্রাম দ্বারা পৃথকীকৃত হয় তাহলে &&, findনিজে কাজ করতে পারেন: পরপর দুই লেখ -execকর্ম এবং দ্বিতীয় শুধুমাত্র যদি মৃত্যুদন্ড কার্যকর করা হবে অবস্থা 0 দিয়ে প্রথম এক প্রস্থান করে।

find . -iname \*.csv -exec grep foo {} \; -exec echo {} \;

(আমি ধরে নিই grepএবং echoএটি কেবল চিত্রের উদ্দেশ্যে, যেমন -exec echoপ্রতিস্থাপন করা যেতে পারে -printএবং ফলস্বরূপ আউটপুটটি যাইহোক বিশেষভাবে কার্যকর হয় না))


2
আমি তার জন্য "$ 0" ব্যবহার এড়াতে চাইছি, কারণ এটি ত্রুটির বার্তা প্রদর্শন করতে শেলও ব্যবহার করে। উদাহরণস্বরূপ, আপনি একটি বিভ্রান্তিকর ./some-file: grep: command not foundত্রুটি বার্তা দেখতে পেলেন । -exec find sh -c '... "$1"' sh {} \;সমস্যা হবে না। আপনার দ্বিতীয় অনুসন্ধান কমান্ডে একটি টাইপো (সম্পর্কিত) রয়েছে।
স্টাফেন চেজেলাস

3

এই নির্দিষ্ট ক্ষেত্রে আমি করব:

find . -iname \*.csv -exec grep -l foo \{\} \;

বা যদি আপনার এসি থাকে :

ack -al -G '.*\.csv' foo

আপনার আসল প্রশ্নের উত্তর দিতে, এর মতো কিছু কাজ করতে পারে:

find . -iname \*.csv -exec sh -c "grep foo {} && echo {}" \;


3
এই পরবর্তী ফাইন্ড কমান্ডটি কেবল অ-বহনযোগ্য নয় এটি খুব বিপজ্জনক কারণ ফাইল পাথগুলি শেল কোড হিসাবে মূল্যায়ন হয়।
স্টাফেন চেজেলাস


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