একাধিক ফাইলে স্ট্রিংয়ের শেষ ঘটনাটি সন্ধান করুন


9

স্ট্রিংয়ের শেষ ঘটনাটি খুঁজতে আমাকে একাধিক লগ ফাইল (সর্বশেষ 24 ঘন্টা উত্পন্ন সমস্ত ফাইল, সমস্ত একই ডিরেক্টরিতে রাখা) অনুসন্ধান করতে হবে। এই হুকুম আমি লিখেছি:

find . -mtime 1 | grep fileprefix | xargs grep 'search string' | tail -1

তবে এটি কেবল একটি ফাইলের জন্য শেষ লাইনটি দেয়। সমস্ত লাইন পেতে কীভাবে এটি টুইট করতে হবে সে সম্পর্কে কোনও পরামর্শ?


আপনি লেজ এবং শেষ গ্রেপ উল্টানোর চেষ্টা করেছেন? অনুসন্ধান . -মটাইম 1 | গ্রেপ ফাইলপ্রিফিক্স | xargs লেজ -1 | গ্রেপ 'অনুসন্ধানের স্ট্রিং'
ম্যাথিউ

উত্তর:


4

জিএনইউ সুবিধাগুলি ধরে নেওয়া:

find . -mtime -1 -exec bash -c \
'for f; do tac "$f" | grep -m1 fileprefix; done' _ {} +

আপনি কি 'বাশ-সি using' এর উদ্দেশ্যটি বিস্তারিতভাবে বর্ণনা করতে পারেন কারণ আমি ইতিমধ্যে ব্যাশ শেলটি ব্যবহার করছি। শেষে '_ {} +' এর উদ্দেশ্য।
লোকেশ

@ লোকেশ, আপনি findব্যবহার করে ফাইলগুলিতে কমান্ড কার্যকর করতে পারেন -exec। এর সাথে bash -c, আমরা একটি bashশাঁস তৈরি করছি যা পাওয়া ফাইলগুলির মধ্য দিয়ে লুপ করে findএবং tac .. | grep -m1 fileprefix
প্রতিটিের

আমি কাট কমান্ড অর্থাৎ চ এর জন্য লুপের জন্য স্ট্রিং ফিল্টারিং প্রসারিত করার চেষ্টা করছিলাম; টাক "$ চ" | grep -m1 ফাইলপ্রিফিক্স | কাট-ডি '' -f4,7-8 তবে আমি কাট কমান্ড দিলে এটি আমার ত্রুটির ফাইলটির অপ্রত্যাশিত পরিণতি দেয়। আমি কি ভুল করছি তা দয়া করে বলতে পারেন?
লোকেশ 5'15

@ লকেশ, -d" "কাট দিয়ে ব্যবহার করুন । একক এর পরিবর্তে ডাবল
উক্তিগুলি

1
findকমান্ড ফাইল উপসর্গ জন্য ফিল্টার করতে পারেন; এর grepজন্য দরকার নেই। এটি অবাক করেও যে অনুসন্ধানের স্ট্রিংটি এই উত্তরে চিত্রিত করে না।
জোনাথন লেফলার 16

8

যদি সমস্ত কিছু একটি ডিরেক্টরিতে থাকে তবে আপনি এটি করতে পারেন:

for file in *fileprefix*; do
    grep 'search string' "$file" | tail -1
done

যদি এগুলি বড় ফাইল হয় tacতবে ফাইলটি বিপরীত ক্রমে (প্রথম লাইনটি প্রথমে) মুদ্রণ করে এবং তারপরে grep -m1প্রথম উপস্থিতির সাথে মিল রেখে গতি বাড়িয়ে তোলা উচিত worth এইভাবে, আপনি পুরো ফাইলটি পড়তে হবে না:

for file in *fileprefix*; do
    tac file | grep -m1 'search string'
done

এই দুজনেই ধরে নিয়েছে যে কোনও ডিরেক্টরি মিলছে না fileprefix। যদি সেখানে থাকে তবে আপনি একটি ত্রুটি পাবেন যা আপনি কেবল উপেক্ষা করতে পারেন। যদি এটি কোনও সমস্যা হয় তবে কেবল ফাইলগুলির জন্য পরীক্ষা করুন:

 for file in *fileprefix*; do
    [ -f "$file" ] && tac file | grep -m1 'search string'
 done

আপনার যদি প্রিন্ট করা ফাইলের নামও প্রয়োজন হয় তবে -Hপ্রতিটি grepঅনুরোধে যুক্ত করুন। অথবা, যদি আপনি grepএটি সমর্থন না করেন তবে এটি অনুসন্ধান করে বলুন /dev/null। এটি আউটপুট পরিবর্তন করবে না তবে যেহেতু grepএকাধিক ফাইল দেওয়া হয়েছে তাই এটি প্রতিটি হিটের জন্য সর্বদা ফাইলের নাম মুদ্রণ করবে:

for file in *fileprefix*; do
    grep 'search string' "$file" /dev/null | tail -1
done

"এইভাবে, আপনি পুরো ফাইলটি পড়া এড়াতে" - আহ? না, আপনি সম্পূর্ণ ফাইলটি গ্রেপ-এ পড়া এড়াতে পারেন তবে আপনি পুরো ফাইলটি ট্যাকের মাধ্যমে রেখে দিয়েছেন। এটি আমার কাছে স্পষ্ট নয় যে এটি আরও দ্রুত হবে, যদিও এটি ম্যাচের শুরুতে বা ফাইলটির শেষের দিকে ছিল কিনা তা নির্ভর করে।
গিলস 21'৩-

@ গিলস না, আপনি পুরো ফাইলটি কোনওটির মধ্যেই রাখেন না tac। প্রথম ম্যাচটি পাওয়া মাত্র এটি বেরিয়ে আসবে। আমি সবেমাত্র একটি 832 এম পাঠ্য ফাইল এবং শেষ লাইনে পাওয়া একটি প্যাটার্ন দিয়ে পরীক্ষা করেছি। grep -m 1 pattern fileসরঞ্জাম ~ 7 সেকেন্ড এবং tac file | grep -m1 patternগ্রহণ 0.009
টেরডন

4
find . ! -name . -prune -mtime 1 -name 'fileprefix*' \
     -exec sed -se'/searchstring/h;$!d;x' {} +

... আপনার যদি জিএনইউ থাকে sedযা -sইপ্রেট ফাইল বিকল্প এবং একটি পসিক্স সমর্থন করে find

আপনার সম্ভবত ! -type dবা বাছাইকারীদের যুক্ত করা উচিত -type f, কারণ ডিরেক্টরি পড়ার চেষ্টা করা খুব কার্যকর হবে না এবং নিয়মিত ফাইলগুলিতে পরিসীমা আরও সংকীর্ণ করা কোনও পাইপ বা সিরিয়াল ডিভাইস ফাইলটিতে পড়া পড়া আটকাতে পারে।

যুক্তিটি অবিশ্বাস্যরূপে সহজ - কোনও পুরানো স্থানের সাথে মেলে এমন কোনও ইনপুট লাইনের অনুলিপিটি দিয়ে sedতার hপুরানো স্থানটি ওভাররাইট করে searchstring, তারপরে dআউটপুট থেকে সমস্ত ইনপুট লাইনগুলি কিন্তু প্রতিটি ইনপুট ফাইলের জন্য শেষ। এটি যখন সর্বশেষ লাইনে পৌঁছে যায় তখন এটি xতার হোল্ড এবং প্যাটার্নের স্পেসগুলি পরিবর্তন করে এবং তাই searchstringযখন এটি ফাইলটি পড়ার সময় পাওয়া যায় তবে সর্বশেষ ঘটনাটি আউটপুটে স্বয়ংক্রিয়ভাবে প্রিন্ট করা হবে, অন্যথায় এটি একটি ফাঁকা রেখা লিখবে। ( যদি এটি অনাকাঙ্ক্ষিত হয় তবে স্ক্রিপ্টের /./!dলেজের সাথে যুক্ত করুন sed)

এটি sedকিছু 65 কে ইনপুট ফাইলগুলি - বা আপনার ARG_MAXসীমা যা হোক না কেন প্রতি একক প্রার্থনা করবে । এটি একটি খুব পারফরম্যান্স সমাধান হওয়া উচিত, এবং এটি বেশ সহজভাবে বাস্তবায়িত হয়।

আপনি যদি সাম্প্রতিক জিএনইউ দিয়েও ফাইলের নামগুলি চান তবে sedআপনি Fকমান্ডের সাহায্যে পৃথক লাইনগুলিতে সেগুলি লিখতে পারেন বা অন্যথায় প্রাথমিকের পরে findসংযোজন করে আপনি প্রতি ব্যাচের জন্য পৃথক তালিকায় মুদ্রণ করতে পারেন ।-print+


1

কেমন:

find . -mtime -1 -name "fileprefix*" -exec sh -c \
'echo "$(grep 'search string' $1 | tail -n 1),$1"' _ {} \;

উপরেরটি আপনাকে প্রতিটি ফাইলের অনুসন্ধানের স্ট্রিংয়ের শেষ ঘটনাটির সাথে কমা পরে সম্পর্কিত ফাইলের নাম (ফর্ম্যাট পরিবর্তন করতে বা অকারণে এটি অপসারণের প্রতিধ্বনিতে ", $ 1" অংশটি সংশোধন করে) এর সাথে একটি সুন্দর আউটপুট দেয়। নমুনা আউটপুট যা "10" নামের উপসর্গের সাথে ফাইলগুলিতে '10' অনুসন্ধানের স্ট্রিং অনুসন্ধান করে:

[dmitry@localhost sourceDir]$ find . -mtime -1 -name "file*" -exec  sh -c 'echo "$(grep '10' $1 | tail -n 1),$1"' _ {} \;
Another data 02 10,./file02.log
Some data 01 10,./file01.log
Yet another data 03 10,./file03.log 

1
find . -mtime 1 -name 'fileprefix*' -exec grep -Hn 'search string' {} + |
    sort -t: -k1,2 -n | 
    awk -F: '{key=$1 ; $1="" ; $2="" ; gsub(/^  /,"",$0); a[key]=$0} 
             END {for (key in a) { print key ":" a[key] }}'

এই ব্যবহার গনুহ grepএর -Hএবং -nবিকল্পগুলি সর্বদা উভয় ফাইলের নাম এবং সব ম্যাচের linenumber প্রিন্ট করতে, তাহলে এটি ফাইলের নাম এবং linenumber এবং পাইপ এটা awk মধ্যে দ্বারা বাছাই করে যা সঞ্চয় একটি অ্যারের প্রতিটি ফাইলের নাম গত ম্যাচে এবং শেষ পর্যন্ত কপি করে প্রিন্ট এটা।

মোটামুটি হিংস্র শক্তি পদ্ধতি, তবে এটি কার্যকর হয়।

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