শেলের মধ্যে, আমি কীভাবে tail
একটি ডিরেক্টরিতে সর্বশেষ ফাইল তৈরি করতে পারি ?
শেলের মধ্যে, আমি কীভাবে tail
একটি ডিরেক্টরিতে সর্বশেষ ফাইল তৈরি করতে পারি ?
উত্তর:
Ls এর আউটপুটকে বিশ্লেষণ করবেন না ! Ls এর আউটপুট পার্সিং করা কঠিন এবং বিশ্বাসযোগ্য নয় ।
আপনার অবশ্যই এটি করতে হলে আমি সন্ধানটি ব্যবহার করার পরামর্শ দিই। মূলত আমি আপনাকে সমাধানটির সূচনা দেওয়ার জন্য এখানে একটি সাধারণ উদাহরণ রেখেছিলাম, তবে যেহেতু এই উত্তরটি কিছুটা জনপ্রিয় বলে মনে হচ্ছে আমি এই সংস্করণটি অনুলিপি করার সিদ্ধান্ত নিয়েছি যা অনুলিপি / আটকানো এবং সমস্ত ইনপুট সহ ব্যবহারের জন্য নিরাপদ provide আরামে বসে আছিস? আমরা একটি অনলাইনার দিয়ে শুরু করব যা আপনাকে বর্তমান ডিরেক্টরিতে সর্বশেষ ফাইল দেবে:
tail -- "$(find . -maxdepth 1 -type f -printf '%T@.%p\0' | sort -znr -t. -k1,2 | while IFS= read -r -d '' -r record ; do printf '%s' "$record" | cut -d. -f3- ; break ; done)"
এখন বেশ অননায়ক না, তাই না? এখানে এটি আবার শেল ফাংশন হিসাবে রয়েছে এবং সহজে পড়ার জন্য ফর্ম্যাট করা হয়েছে:
latest-file-in-directory () {
find "${@:-.}" -maxdepth 1 -type f -printf '%T@.%p\0' | \
sort -znr -t. -k1,2 | \
while IFS= read -r -d '' -r record ; do
printf '%s' "$record" | cut -d. -f3-
break
done
}
এবং এখন এটি অনলাইনার হিসাবে:
tail -- "$(latest-file-in-directory)"
যদি সমস্ত কিছু ব্যর্থ হয় তবে আপনি উপরের ফাংশনটি নিজের মধ্যে অন্তর্ভুক্ত করতে পারেন .bashrc
এবং একটি ক্যাব্যাট দিয়ে সমস্যার সমাধানের বিষয়টি বিবেচনা করতে পারেন। আপনি যদি সবেমাত্র কাজটি করতে চান তবে আপনার আর পড়ার দরকার নেই।
এর সাথে সতর্কবাণীটি হ'ল এক বা একাধিক নতুন লাইনে শেষ হওয়া কোনও ফাইলের নামটি এখনও tail
সঠিকভাবে পাস করা হবে না। এই সমস্যাটির আশেপাশে কাজ করা জটিল এবং আমি এটিকে পর্যাপ্ত বিবেচনা করি যে এই জাতীয় দূষিত ফাইল নামটি যদি আরও বিপজ্জনক কিছু না করে "এই জাতীয় কোনও ফাইল" ত্রুটি ঘটবে তার তুলনামূলকভাবে নিরাপদ আচরণের মুখোমুখি হয়।
কৌতূহলের জন্য এটি এটি কীভাবে কাজ করে, কেন এটি নিরাপদ এবং কেন অন্যান্য পদ্ধতি সম্ভবত তা নয় তার ক্লান্তিকর ব্যাখ্যা।
প্রথমত, ফাইল পাথগুলি সীমিত করতে নিরাপদ কেবল বাইটটি বাতিল হয় কারণ এটি ইউনিক্স সিস্টেমে ফাইল পাথগুলিতে সর্বজনীনভাবে নিষিদ্ধ। ফাইল পাথের কোনও তালিকা কেবলমাত্র একটি ডিলিমিটার হিসাবে নাল ব্যবহার করার জন্য এবং কোনও প্রোগ্রাম থেকে অন্য প্রোগ্রামে একটি ফাইলের পাথ হস্তান্তর করার সময়, এমন পদ্ধতিতে এমন কাজ করা গুরুত্বপূর্ণ যেগুলি স্বেচ্ছাচারিত বাইটগুলিতে হ্রাস পাবে না। এটি এবং অন্যান্য সমস্যাগুলি সমাধান করার অনেকগুলি আপাতদৃষ্টিতে সঠিক উপায় রয়েছে যা ধরে নিয়েই ব্যর্থ হয় (এমনকি দুর্ঘটনাক্রমে) যে ফাইলের নামগুলিতে কোনও নতুন লাইন বা স্পেস থাকবে না। অনুমানও নিরাপদ নয়।
আজকের উদ্দেশ্যগুলির জন্য প্রথম ধাপটি হ'ল ফাইলগুলির একটি নাল-সীমিত তালিকা পাওয়া। আপনার যদি find
জিএনইউ'র -print0
মতো সমর্থনকারী থাকে তবে এটি বেশ সহজ :
find . -print0
তবে এই তালিকাটি এখনও আমাদের জানায় না কোনটি নতুন। তাই আমাদের সেই তথ্যটি অন্তর্ভুক্ত করতে হবে। আমি -printf
ফাইন্ডের স্যুইচটি ব্যবহার করা চয়ন করি যা আমাকে আউটপুটে কী ডেটা প্রদর্শিত হবে তা নির্দিষ্ট করতে দেয়। find
সমর্থনের সমস্ত সংস্করণ নয় -printf
(এটি মানক নয়) তবে জিএনইউ এটি খুঁজে পায়। যদি আপনি নিজেকে ছাড়া নিজেকে খুঁজে পান তবে আপনাকে -printf
নির্ভর করতে হবে -exec stat {} \;
কোন মুহুর্তে আপনাকে বহনযোগ্যতার সমস্ত আশা ত্যাগ করতে হবে কারণ stat
এটি আদর্শ নয়। আপাতত আমি ধরে নিচ্ছি আপনার কাছে জিএনইউ সরঞ্জাম রয়েছে।
find . -printf '%T@.%p\0'
এখানে আমি প্রিন্টফ ফর্ম্যাটটির জন্য জিজ্ঞাসা করছি %T@
যা ইউনিক্সের সূচনার সময় থেকেই সেকেন্ডে সংশোধন সময়, পরে একটি পিরিয়ড এবং তার পরে একটি সেকেন্ডের ভগ্নাংশ নির্দেশ করে এমন একটি সংখ্যার পরে। %p
নাল বাইটের সাথে শেষ হওয়ার আগে আমি এটিকে আরও একটি পিরিয়ড এবং তারপরে (যা ফাইলটির পুরো পথ) add
এখন আমার আছে
find . -maxdepth 1 \! -type d -printf '%T@.%p\0'
এটি বলার অপেক্ষা রাখে না তবে সাব ডিরেক্টরি এবং সাবস্ক্রিপশন ডিরেক্টরিগুলির সামগ্রীর তালিকাবদ্ধকরণ থেকে সম্পূর্ণ -maxdepth 1
প্রতিরোধ করা find
হতে পারে \! -type d
যা আপনি চান না tail
। এখন পর্যন্ত আমার কাছে বর্তমান ডিরেক্টরিতে সংশোধন সময়ের তথ্য সহ ফাইল রয়েছে, সুতরাং এখন আমার সেই পরিবর্তনকাল অনুসারে বাছাই করা দরকার।
ডিফল্টরূপে sort
এটির ইনপুটটি নতুন লাইন-সীমিত রেকর্ড হিসাবে প্রত্যাশা করে। আপনার যদি জিএনইউ থাকে তবে sort
আপনি -z
স্যুইচটি ব্যবহার করে নাল-সীমাবদ্ধ রেকর্ডের আশা করতে বলতে পারেন; মান sort
জন্য কোন সমাধান নেই। আমি কেবল প্রথম দুটি সংখ্যা (সেকেন্ড এবং একটি সেকেন্ডের ভগ্নাংশ) অনুসারে বাছাই করতে আগ্রহী এবং আসল ফাইলের নাম অনুসারে বাছাই করতে চাই না তাই আমি sort
দুটি জিনিস বলি : প্রথমত, এটি পিরিয়ড বিবেচনা করা উচিত ( .
) একটি ক্ষেত্রের ডিলিমিটার এবং দ্বিতীয়টি কীভাবে রেকর্ডগুলি বাছাই করতে হবে তা বিবেচনা করার সময় এটি কেবল প্রথম এবং দ্বিতীয় ক্ষেত্রগুলি ব্যবহার করা উচিত।
| sort -znr -t. -k1,2
সবার আগে আমি তিনটি সংক্ষিপ্ত বিকল্পগুলি বান্ডিল করছি যা একসাথে কোনও মূল্য নেয় না; -znr
বলার কেবল একটি সংক্ষিপ্ত উপায় -z -n -r
)। এর পরে -t .
(স্থানটি isচ্ছিক) sort
ক্ষেত্রের সীমানার চরিত্রটি বলে এবং -k 1,2
ক্ষেত্রের সংখ্যাগুলি নির্দিষ্ট করে: প্রথম এবং দ্বিতীয় ( sort
এক থেকে ক্ষেত্র গণনা করে শূন্য নয়)। মনে রাখবেন যে বর্তমান ডিরেক্টরিটির জন্য একটি নমুনা রেকর্ডটি দেখতে পাবেন:
1000000000.0000000000../some-file-name
এর অর্থ এই রেকর্ডটি অর্ডার করার পরে sort
প্রথমে 1000000000
এবং তারপরে দেখবে 0000000000
। -n
বিকল্প বলে sort
যখন এই মান তুলনা সাংখ্যিক তুলনা ব্যবহার, কারণ যদি দুটি মানই নম্বর আছে। সংখ্যাগুলি নির্দিষ্ট দৈর্ঘ্যের হওয়ার কারণে এটি গুরুত্বপূর্ণ নয় তবে এটি কোনও ক্ষতি করে না।
দেওয়া অন্যান্য সুইচ sort
হয় -r
জন্য "বিপরীত।" ডিফল্ট হিসাবে একটি সংখ্যার সাজানোর আউটপুট প্রথমে সর্বনিম্ন সংখ্যা হবে, -r
এটি পরিবর্তন করে যাতে এটি সর্বনিম্ন এবং সর্বশেষে সর্বোচ্চ সংখ্যার তালিকা করে। যেহেতু এই সংখ্যাগুলি টাইমস্ট্যাম্পগুলি বেশি তার অর্থ নতুনতর হবে এবং এটি তালিকার শুরুতে নতুন রেকর্ডটি রাখে।
ফাইল পাথগুলির তালিকাটি যেহেতু এটি থেকে sort
উঠে এসেছে এখন তার পছন্দসই উত্তর রয়েছে যা আমরা ঠিক উপরে খুঁজছি। যা অবশিষ্ট রয়েছে তা হ'ল অন্য রেকর্ডগুলি ফেলে দেওয়ার এবং টাইমস্ট্যাম্পটি সরিয়ে ফেলার কোনও উপায় find দুর্ভাগ্যক্রমে এমনকি জিএনইউ head
এবং tail
নাল-সীমাবদ্ধ ইনপুটটিতে তাদের চালিত করতে সুইচগুলি গ্রহণ করে না। পরিবর্তে আমি এক ধরণের দরিদ্র লোক হিসাবে কিছুক্ষণ লুপ ব্যবহার করি head
।
| while IFS= read -r -d '' record
প্রথমে আমি আনসেট করি IFS
যাতে ফাইলগুলির তালিকা শব্দের বিভাজনের সাথে সম্পর্কিত না হয়। পরবর্তী আমি read
দুটি জিনিস বলি : ইনপুট ( -r
) এর মধ্যে পালানোর ক্রমগুলির ব্যাখ্যা করবেন না এবং ইনপুটটি নাল বাইট ( -d
) দিয়ে সীমিত করা হয় ; এখানে শূন্য স্ট্রিংটি ''
নুল দ্বারা ডিলিমেটেড "কোনও ডিলিমিটার" না করতে নির্দেশ করতে ব্যবহৃত হয়। প্রতিটি রেকর্ডটি ভেরিয়েবলটিতে পড়তে হবে record
যাতে প্রতিটি সময় while
লুপটি পুনরাবৃত্তি করে তবে এটির একটি একক টাইমস্ট্যাম্প এবং একটি ফাইলের নাম থাকবে। নোট যে -d
একটি GNU এক্সটেনশান; আপনার যদি কেবল একটি মান থাকে তবে read
এই কৌশলটি কার্যকর হবে না এবং আপনার খুব কম সংস্থান রয়েছে।
আমরা জানি যে record
ভেরিয়েবলের এর তিনটি অংশ রয়েছে, সমস্তই পিরিয়ড ক্যারেক্টার দ্বারা সীমিত করা হয়। cut
ইউটিলিটি ব্যবহার করে এগুলির একটি অংশ বের করা সম্ভব।
printf '%s' "$record" | cut -d. -f3-
এখানে পুরো রেকর্ডটি printf
সেখানে পৌঁছে দেওয়া হয়েছে এবং সেখান থেকে পাইপ করা হয়েছে cut
; ব্যাশ আপনি একটি ব্যবহার করে এই আরও প্রক্রিয়া সহজ পারে এখানে স্ট্রিং থেকে cut -d. -3f- <<<"$record"
ভাল অভিনয়ের জন্য। আমরা cut
দুটি জিনিস বলি : প্রথমে -d
এটি ক্ষেত্রগুলি চিহ্নিত করার জন্য একটি নির্দিষ্ট সীমানা করা উচিত (যেমন sort
ডিলিমিটার .
ব্যবহৃত হয়)। দ্বিতীয়টি নির্দিষ্ট ক্ষেত্রগুলি থেকে কেবল মানগুলি মুদ্রণের cut
জন্য নির্দেশিত -f
; ক্ষেত্রের তালিকাটি এমন একটি পরিসীমা হিসাবে দেওয়া হয় 3-
যা তৃতীয় ক্ষেত্র এবং সমস্ত নিম্নলিখিত ক্ষেত্রের থেকে মান নির্দেশ করে। এর অর্থ এটি রেকর্ডটিতে পাওয়া cut
দ্বিতীয়টি সহ সমস্ত কিছু পড়তে এবং উপেক্ষা .
করবে এবং তারপরে বাকীটি মুদ্রণ করবে যা ফাইলের পথ অংশ।
সর্বাধিক নতুন ফাইল পাথ মুদ্রণের পরেও চালিয়ে যাওয়ার দরকার নেই: break
দ্বিতীয় ফাইলের পথে না যেতে লুপটি প্রস্থান করে।
tail
এই পাইপলাইনের দ্বারা ফিরিয়ে দেওয়া ফাইলের পথে চলমান একমাত্র জিনিস । আপনি আমার উদাহরণে লক্ষ্য করতে পারেন যে আমি সাবসেলের পাইপলাইনটি বন্ধ করে এটি করেছি; আপনি যা খেয়াল করতে পারেন না তা হ'ল আমি সাব-শেলটি ডাবল কোটে আবদ্ধ করেছি। এটি গুরুত্বপূর্ণ কারণ শেষ পর্যন্ত এমনকি কোনও ফাইলের নামের জন্য নিরাপদ থাকার এই সমস্ত প্রচেষ্টা সহ অব্যক্ত সাবস্কেল সম্প্রসারণ এখনও জিনিসগুলিকে ভেঙে দিতে পারে। একটি আরো বিস্তারিত ব্যাখ্যা আপনি আগ্রহী হলে পাওয়া যায়। অনুরোধের দ্বিতীয় গুরুত্বপূর্ণ তবে সহজেই উপেক্ষিত দিকটি tail
হ'ল --
ফাইলের নামটি প্রসারিত করার আগে আমি এটিতে বিকল্পটি সরবরাহ করেছিলাম । এটি নির্দেশ দেবেtail
আর কোনও বিকল্প নির্দিষ্ট করা হচ্ছে না এবং নীচের সমস্ত কিছুই একটি ফাইলের নাম, যা ফাইল ফাইলের নামগুলি শুরু করে এটি পরিচালনা করা নিরাপদ করে -
।
tail -f $(find . -type f -exec stat -f "%m {}" {} \;| sort -n | tail -n 1 | cut -d ' ' -f 2)
head
এবং tail
নাল-সীমাবদ্ধ ইনপুটটিতে তাদের চালিত করতে সুইচগুলি গ্রহণ করে না।" আমার প্রতিস্থাপন head
: … | grep -zm <number> ""
।
tail `ls -t | head -1`
যদি আপনি শূন্যস্থান সহ ফাইলের নামগুলি নিয়ে উদ্বিগ্ন হন,
tail "`ls -t | head -1`"
তুমি ব্যবহার করতে পার:
tail $(ls -1t | head -1)
$()
কনস্ট্রাক্ট একটি উপ-শেল যা কমান্ড সঞ্চালিত শুরু ls -1t
করে দিয়ে বংশীধ্বনিতুল্য (সময় অনুক্রমে সমস্ত ফাইল, প্রতি লাইনে একটি তালিকা) head -1
প্রথম লাইন (ফাইল) জন্য।
এই কমান্ডের আউটপুট (অতি সাম্প্রতিক ফাইল) এর পরে tail
প্রক্রিয়া করার জন্য পাস করা হয়।
মনে রাখবেন যে এটি ডিরেক্টরি তৈরির ঝুঁকি নিয়ে চলে যদি এটি সর্বাধিক সাম্প্রতিক ডিরেক্টরি এন্ট্রি তৈরি করা হয়। আমি সেই কৌশলটি একটি উলামে ব্যবহার করেছি একটি ডিরেক্টরিতে সর্বাধিক সাম্প্রতিক লগ ফাইল (একটি ঘোরানো সেট থেকে) সম্পাদনা করার জন্য কেবল সেই লগ ফাইলগুলিই রয়েছে।
-1
প্রয়োজন নেই, ls
যখন এটি একটি নল আছে আপনার জন্য আছে যে। উদাহরণস্বরূপ তুলনা করুন ls
এবং করুন ls|cat
।
পসিক্স সিস্টেমে "সর্বশেষ নির্মিত" ডিরেক্টরি এন্ট্রি পাওয়ার কোনও উপায় নেই। প্রতিটি ডিরেক্টরি এন্ট্রি রয়েছে atime
, mtime
এবং ctime
, তবে মাইক্রোসফ্ট উইন্ডোজের বিপরীতে, এর ctime
অর্থ ক্রিয়েশনটাইম নয়, "শেষ স্থিতির পরিবর্তনের সময়"।
সুতরাং আপনি সবচেয়ে ভাল পেতে পারেন "সর্বশেষ সম্প্রতি পরিবর্তিত ফাইলটি লেজু করা", যা অন্য উত্তরে ব্যাখ্যা করা হয়েছে। আমি এই আদেশের পক্ষে যাব:
লেজ -f "$ (ls -tr | সেড 1 কিউ)"
ls
কমান্ডের চারপাশে উদ্ধৃতিগুলি নোট করুন । এটি প্রায় সমস্ত ফাইলের নাম সহ স্নিপেট কাজ করে।
ইন zsh
:
tail *(.om[1])
দেখুন: http://zsh.sourceforge.net/Doc/Release/Expansion.html# গ্লোব-কোয়ালিফায়ারগুলি , এখানে m
পরিবর্তনের সময়কে বোঝায় m[Mwhms][-|+]n
এবং পূর্ববর্তীটির o
অর্থ এটি একটি উপায়ে বাছাই করা হয়েছে ( O
এটি অন্যভাবে সাজান)। .
একমাত্র উপায় নিয়মিত ফাইল। বন্ধনীগুলির [1]
মধ্যে প্রথম আইটেমটি বাছাই করে। তিনটি ব্যবহার বাছাই করতে [1,3]
, প্রাচীনতম ব্যবহারটি পেতে [-1]
।
এটি খুব ছোট এবং ব্যবহার করে না ls
।
এটি করার জন্য সম্ভবত এক মিলিয়ন উপায় রয়েছে তবে আমি যেভাবে এটি করব তা হ'ল:
tail `ls -t | head -n 1`
ব্যাকটিক্সের মধ্যে বিটগুলি (অক্ষরের মতো উদ্ধৃতি) ব্যাখ্যা করা হয় এবং ফলটি লেজতে ফিরে আসে।
ls -t #gets the list of files in time order
head -n 1 # returns the first line only
আমার স্নাতকের:
tail -f /path/to/directory/*
আমার জন্য ঠিক কাজ করে।
আপনি টেল কমান্ড শুরু করার পরে উত্পন্ন ফাইলগুলি পেতে সমস্যা are তবে আপনার যদি এটির প্রয়োজন না হয় (যেমন উপরের সমস্ত সমাধানগুলি এটির জন্য যত্নশীল নয়), অস্ট্রিকটি কেবল সহজ সমাধান, আইএমও।
কেউ এটি পোস্ট করেছেন এবং তারপরে এটি কোনও কারণে মুছে ফেলা হয়েছে তবে এটি কেবলমাত্র কাজ করে, তাই ...
tail -f `ls -tr | tail`
ls
সবচেয়ে স্মার্ট জিনিস নয় ...
tail -f `ls -lt | grep -v ^d | head -2 | tail -1 | tr -s " " | cut -f 8 -d " "`
ব্যাখ্যা: