নতুন ফাইলের মিলের প্যাটার্নটি সন্ধান করতে ফাংশনটি বাশ করুন Bash


141

বাশ-এ, আমি এমন একটি ফাংশন তৈরি করতে চাই যা একটি নির্দিষ্ট প্যাটার্নের সাথে মেলে এমন নতুন ফাইলটির ফাইল নাম দেয় returns উদাহরণস্বরূপ, আমার কাছে ফাইলগুলির ডিরেক্টরি রয়েছে:

Directory/
   a1.1_5_1
   a1.2_1_4
   b2.1_0
   b2.2_3_4
   b2.3_2_0

আমি নতুন ফাইলটি চাই যা 'বি 2' দিয়ে শুরু হয়। বাশে আমি কীভাবে এটি করব? আমার ~/.bash_profileস্ক্রিপ্টে এটি থাকা দরকার।


4
আরও উত্তরের ইঙ্গিতের জন্য দেখুন superuser.com / প্রশ্নগুলি / 294161/…। বাছাই করা আপনার সর্বশেষতম ফাইলটি পাওয়ার মূল পদক্ষেপ
ওল্ফগ্যাং ফাহল

উত্তর:


229

lsকমান্ড একটি প্যারামিটার রয়েছে -tসময় দ্বারা সাজাতে হয়। এরপরে আপনি প্রথমটি (নবীনতম) সাথে দখল করতে পারেন head -1

ls -t b2* | head -1

তবে সাবধান থাকুন: কেন আপনি এলএস এর আউটপুট বিশ্লেষণ করবেন না

আমার ব্যক্তিগত মতামত: পার্সিং lsকেবল তখনই বিপজ্জনক যখন ফাইলের নামগুলিতে স্পেস বা নিউলাইনগুলির মতো মজার চরিত্র থাকতে পারে। যদি আপনি গ্যারান্টি দিতে পারেন যে ফাইলের নামগুলিতে মজাদার অক্ষর থাকবে না তবে পার্সিং lsকরা বেশ নিরাপদ।

আপনি যদি এমন কোনও স্ক্রিপ্ট বিকাশ করছেন যা বোঝা যায় যে অনেক লোক দ্বারা বিভিন্ন সিস্টেমে অনেকগুলি বিভিন্ন পরিস্থিতিতে চালিত করা হয় তবে আমি পার্স না করার পরামর্শ দিই ls

এটি কীভাবে "ডান" করবেন তা এখানে রয়েছে: আমি কীভাবে একটি ডিরেক্টরিতে সর্বশেষ (সর্বাধিক প্রাচীনতম, প্রাচীনতম) ফাইলটি সন্ধান করতে পারি?

unset -v latest
for file in "$dir"/*; do
  [[ $file -nt $latest ]] && latest=$file
done

8
অন্যদের কাছে নোট করুন: আপনি যদি কোনও ডিরেক্টরিতে এটি করে থাকেন তবে আপনি 'ls -td <Pattern> | এর মতো ls -d বিকল্পটি যুক্ত করবেন add শিরোনাম -1 '
ken.ganong

5
পার্সিং নির্মিত LS লিঙ্কটি রয়েছে তারা এই না বলে এবং পদ্ধতি বিশেষ পরামর্শ দেওয়া হচ্ছে BashFAQ 99 । আমি কোনও স্ক্রিপ্টে অন্তর্ভুক্ত করার জন্য বুলেট-প্রুফের কিছু চেয়ে 1-লাইনারের সন্ধান করছি, তাই আমি @lesmana এর মত নিরাপদে ls পার্স করা চালিয়ে যাব।
এপিমনাম

1
@ নামবিহীন: আপনি যদি ভঙ্গুরটি ব্যবহার না করে একটি লাইনার সন্ধান করছেন ls, printf "%s\n" b2* | head -1এটি আপনার জন্য করবে।
ডেভিড ওঙ্গারো

2
@ ডেভিডঅঙ্গারো প্রশ্নটি ফাইল নামগুলির সংস্করণ সংখ্যা নয় তা বলে না। এটি প্রায় সময় পরিবর্তনের সময়। এমনকি ফাইলের নাম ধরে নিয়ে b2.10_5_2এই সমাধানটিকে হত্যা করে।
এপোনামাস

1
আপনার এক লাইনার আমাকে সঠিক উত্তর দিচ্ছেন, তবে "ডান" উপায়টি আসলে আমাকে সবচেয়ে প্রাচীন ফাইল দিচ্ছে । কোন ধারণা কেন?
নিউনামস্ট্যাট

15

সংমিশ্রণ findএবং lsজন্য ভাল কাজ করে

  • নতুন লাইন ছাড়া ফাইলের নাম
  • খুব বড় পরিমাণে ফাইল নয়
  • খুব দীর্ঘ ফাইলের নাম নয়

সমাধান:

find . -name "my-pattern" -print0 |
    xargs -r -0 ls -1 -t |
    head -1

আসুন এটি ভেঙে দিন:

এর সাথে findআমরা এর মতো সমস্ত আকর্ষণীয় ফাইল মেলাতে পারি:

find . -name "my-pattern" ...

তারপরে ব্যবহার করে -print0আমরা সমস্ত ফাইলের নাম নিরাপদে lsএটিকে দিতে পারি:

find . -name "my-pattern" -print0 | xargs -r -0 ls -1 -t

অতিরিক্ত findঅনুসন্ধান পরামিতি এবং নিদর্শন এখানে যুক্ত করা যেতে পারে

find . -name "my-pattern" ... -print0 | xargs -r -0 ls -1 -t

ls -tসংশোধন সময় (নতুনতম) দ্বারা ফাইলগুলি বাছাই করে এবং এটি একটি লাইনে মুদ্রণ করবে। আপনি -cতৈরির সময় অনুসারে বাছাই করতে ব্যবহার করতে পারেন। দ্রষ্টব্য : এটি নতুনলাইনযুক্ত ফাইলের নামগুলির সাথে ভেঙে যাবে।

পরিশেষে head -1আমাদের সাজানো তালিকার প্রথম ফাইলটি পায়।

দ্রষ্টব্য: xargs আর্গুমেন্ট তালিকার আকারে সিস্টেম সীমা ব্যবহার করুন। যদি এই আকারটি অতিক্রম করে তবে একাধিকবার xargsকল করবে ls। এটি বাছাই এবং সম্ভবত চূড়ান্ত আউটপুট ভঙ্গ করবে। চালান

xargs  --show-limits

আপনার সিস্টেমে সীমাবদ্ধতা পরীক্ষা করতে to

নোট 2:find . -maxdepth 1 -name "my-pattern" -print0 আপনি সাবফোল্ডারগুলির মাধ্যমে ফাইলগুলি অনুসন্ধান করতে না চাইলে ব্যবহার করুন ।

নোট 3: @ স্টারফ্রাই দ্বারা নির্দেশিত হিসাবে - -rআর্গুমেন্টের xargsকলটি রোধ করা হচ্ছে ls -1 -t, যদি কোনও ফাইলের সাথে মেলে না find। মিষ্টি জন্য আপনাকে ধন্যবাদ।


2
এটি ls ভিত্তিক সমাধানগুলির চেয়ে ভাল, কারণ এটি অনেকগুলি ফাইলের ডিরেক্টরিতে কাজ করে যেখানে ls chokes।
মার্সিন জুকোভস্কি

find . -name "my-pattern" ... -print0আমাকে দেয়find: paths must precede expression: `...'
যাক্কো

উহু! ..."আরও বেশি পরামিতি" বোঝায়। আপনার যদি এটির প্রয়োজন না হয় তবে এটি বাদ দিন।
বরিস

2
আমি দেখেছি যে এটি এমন কোনও ফাইল ফেরত দিতে পারে যা প্যাটার্নের সাথে মেলে না এমন কোনও ফাইল না থাকলে প্যাটার্নের সাথে মেলে না। এটি ঘটে কারণ xargs তে কিছুই পাস করে না যা এরপরে কোনও ফাইল তালিকা ছাড়াই ls কে অনুরোধ করে, যার ফলে এটি সমস্ত ফাইলে কাজ করে। সমাধানটি হ'ল -rxargs কমান্ড-লাইনে যুক্ত করা যা xargs কে বলে যে যদি এটির স্ট্যান্ডার্ড ইনপুটটিতে কিছু না পায় তবে তার কমান্ড-লাইনটি চালাবেন না।
স্টারফ্রি

@ স্টারফ্রি আপনাকে ধন্যবাদ! সুন্দর ক্যাচ. আমি -rউত্তর যোগ ।
বোরিস ব্রডস্কি

7

এটি প্রয়োজনীয় বাশ ফাংশনটির সম্ভাব্য বাস্তবায়ন:

# Print the newest file, if any, matching the given pattern
# Example usage:
#   newest_matching_file 'b2*'
# WARNING: Files whose names begin with a dot will not be checked
function newest_matching_file
{
    # Use ${1-} instead of $1 in case 'nounset' is set
    local -r glob_pattern=${1-}

    if (( $# != 1 )) ; then
        echo 'usage: newest_matching_file GLOB_PATTERN' >&2
        return 1
    fi

    # To avoid printing garbage if no files match the pattern, set
    # 'nullglob' if necessary
    local -i need_to_unset_nullglob=0
    if [[ ":$BASHOPTS:" != *:nullglob:* ]] ; then
        shopt -s nullglob
        need_to_unset_nullglob=1
    fi

    newest_file=
    for file in $glob_pattern ; do
        [[ -z $newest_file || $file -nt $newest_file ]] \
            && newest_file=$file
    done

    # To avoid unexpected behaviour elsewhere, unset nullglob if it was
    # set by this function
    (( need_to_unset_nullglob )) && shopt -u nullglob

    # Use printf instead of echo in case the file name begins with '-'
    [[ -n $newest_file ]] && printf '%s\n' "$newest_file"

    return 0
}

এটি কেবল বাশ অন্তর্নির্মিত ব্যবহার করে এবং এমন ফাইলগুলি পরিচালনা করতে হবে যার নামগুলিতে নিউলাইন বা অন্যান্য অস্বাভাবিক অক্ষর রয়েছে।


1
আপনি ব্যবহার করতে পারেন nullglob_shopt=$(shopt -p nullglob)এবং তারপরে এটি পূর্বে কেমন ছিল তা $nullglobফিরিয়ে দিতে nullglob
gniourf_gniourf 21

@Gniourf_gniourf use (শপট-পি নাল্লগ্লোব) ব্যবহার করার পরামর্শটি একটি ভাল। আমি সাধারণত কমান্ড সাবস্টিটিউশন ( $()বা ব্যাকটিক্স) ব্যবহার এড়াতে চেষ্টা করি কারণ এটি ধীরে ধীরে, বিশেষত সাইগউইনের অধীনে, এমনকি যখন কমান্ডটি কেবল বিল্টইন ব্যবহার করে। এছাড়াও, কমান্ডগুলি চালিত হওয়া সাব-শেল প্রসঙ্গে কখনও কখনও তাদের অপ্রত্যাশিত পদ্ধতিতে আচরণ করতে পারে। আমি ভেরিয়েবলগুলিতে কমান্ডগুলি সংরক্ষণ করার চেষ্টাও করি (যেমন nullglob_shopt) কারণ ভেরিয়েবলের মানটি ভুল পেলে খুব খারাপ জিনিস ঘটতে পারে।
pjh

আমি বিশদগুলিতে মনোযোগের প্রশংসা করি যা উপেক্ষা করা হলে অস্পষ্ট ব্যর্থতা হতে পারে। ধন্যবাদ!
রন বার্ক

আমি ভালোবাসি যে আপনি সমস্যাটি সমাধান করার জন্য আরও অনন্য উপায়ের জন্য গিয়েছিলেন! এটি নিশ্চিত যে ইউনিক্স / লিনাক্সে 'ত্বকের চামড়া' করার একাধিক উপায় রয়েছে cat। এমনকি যদি এটি আরও বেশি কাজ নেয় তবে এতে মানুষের ধারণাগুলি দেখানোর সুবিধা রয়েছে। একটি +1 আছে!
প্রাইফটান

3

অস্বাভাবিক ফাইলের নাম (যেমন বৈধ \nঅক্ষরযুক্ত একটি ফাইল এই জাতীয় পার্সিংয়ের সাহায্যে বিপর্যয় ডেকে আনতে পারে Per পার্লে এটি করার একটি উপায় এখানে রয়েছে:

perl -le '@sorted = map {$_->[0]} 
                    sort {$a->[1] <=> $b->[1]} 
                    map {[$_, -M $_]} 
                    @ARGV;
          print $sorted[0]
' b2*

এটি সেখানে শোয়ার্টজিয়ান রূপান্তর ব্যবহৃত হয়।


1
স্কুলটি আপনার সাথে থাকুক!
নাথান মন্টিলিওন

এই উত্তরটি কার্যকর হতে পারে তবে দুর্বল ডকুমেন্টেশনের কারণে আমি এটিতে বিশ্বাস করব না।
ওল্ফগ্যাং ফাহল

1

আপনি statকোনও ফাইল গ্লোব এবং সামনের অংশে যুক্ত ফাইলের সময়ের সাথে একটি সাজসজ্জা-সাজানো-আনকোরেট ব্যবহার করতে পারেন :

$ stat -f "%m%t%N" b2* | sort -rn | head -1 | cut -f2-

নাঃ। "স্ট্যাটাস: '% m% t% N' এর জন্য ফাইল সিস্টেমের তথ্য পড়তে পারে না: এ জাতীয় কোনও ফাইল বা ডিরেক্টরি নেই"
কেন

আমি মনে করি এটি ম্যাক / ফ্রিবিএসডি সংস্করণের জন্য হতে পারে stat, যদি আমি এর বিকল্পগুলি সঠিকভাবে মনে রাখি। অন্যান্য প্ল্যাটফর্মগুলিতে অনুরূপ আউটপুট পেতে, আপনি ব্যবহার করতে পারেনstat -c $'%Y\t%n' b2* | sort -rn | head -n1 | cut -f2-
জেফ্রি ক্যাশ

1

যারা find ... xargs ... head ...উপরের সমাধানটি চান তাদের জন্য অন্ধকার যাদু ফাংশন জ্বলন , তবে সহজেই ফাংশন ফর্মটি ব্যবহার করতে পারেন যাতে আপনাকে ভাবতে হবে না:

#define the function
find_newest_file_matching_pattern_under_directory(){
    echo $(find $1 -name $2 -print0 | xargs -0 ls -1 -t | head -1)
}

#setup:
#mkdir /tmp/files_to_move
#cd /tmp/files_to_move
#touch file1.txt
#touch file2.txt

#invoke the function:
newest_file=$( find_newest_file_matching_pattern_under_directory /tmp/files_to_move/ bc* )
echo $newest_file

ছাপে:

file2.txt

যা হলো:

প্রদত্ত প্যাটার্নটির সাথে মেলে প্রদত্ত ডিরেক্টরিটির আওতায় ফাইলের সবচেয়ে পুরানো সংশোধিত টাইমস্ট্যাম্পের সাথে ফাইলের নাম।


1

ফাইন্ড কমান্ডটি ব্যবহার করুন।

ধরে নিই যে আপনি বাশ 4.2+ ব্যবহার -printf '%T+ %p\n'করছেন, ফাইল টাইমস্ট্যাম্প মানটির জন্য ব্যবহার করুন।

find $DIR -type f -printf '%T+ %p\n' | sort -r | head -n 1 | cut -d' ' -f2

উদাহরণ:

find ~/Downloads -type f -printf '%T+ %p\n' | sort -r | head -n 1 | cut -d' ' -f2

আরও দরকারী স্ক্রিপ্টের জন্য, সন্ধানের সর্বশেষ স্ক্রিপ্টটি এখানে দেখুন: https://github.com/l3x/helpers


ফাঁকা স্থান পরিবর্তন করে এমন ফাইলের নাম নিয়ে কাজ করতে '-f2,3,4,5,6,7,8,9 ...
ভালডজকা

0

এটি অর্জনের আরও অনেক কার্যকর উপায় রয়েছে। নিম্নলিখিত আদেশটি বিবেচনা করুন:

find . -cmin 1 -name "b2*"

এই কমান্ডটি "বি 2 *" -তে ওয়াইল্ডকার্ড অনুসন্ধানের সাথে এক মিনিট আগে উত্পাদিত সর্বশেষ ফাইলটি আবিষ্কার করে। আপনি যদি গত দুটি দিন থেকে ফাইলগুলি চান তবে নীচের কমান্ডটি ব্যবহার করে আপনি আরও ভাল হতে পারবেন:

find . -mtime 2 -name "b2*"

দ্য "." বর্তমান ডিরেক্টরি প্রতিনিধিত্ব করে। আশাকরি এটা সাহায্য করবে.


9
এটি আসলে "সর্বাধিক নতুন ফাইলের মিলের প্যাটার্ন" সন্ধান করে না ... এটি কেবল এক মিনিট আগে তৈরি করা ফাইলগুলি বা দুটি দিন আগে সংশোধিত সমস্ত ফাইলের সন্ধান করে।
GnP

এই উত্তর উত্থাপিত প্রশ্নের উপর ভিত্তি করে ছিল। এছাড়াও, আপনি এক দিন বা তার আগে এসেছিল সর্বশেষতম ফাইলটি দেখার জন্য কমান্ডটি টুইট করতে পারেন। এটি আপনি কী করতে চাইছেন তার উপর নির্ভর করে।
নওফাল

"টুইট" উত্তর নয়। এটি একটি উত্তর হিসাবে পোস্ট করার মতো: "সন্ধানের আদেশটি কেবল সামঞ্জস্য করুন এবং আপনি যা করতে চান তার উপর নির্ভর করে উত্তরটি সন্ধান করুন"।
কেনেট সেলেস্তে

অপ্রয়োজনীয় মন্তব্য সম্পর্কে নিশ্চিত নয়। আপনি যদি মনে করেন আমার উত্তরটি দৃstan়রূপে আসে না, তবে দয়া করে কেন আমার উত্তরটি উদাহরণের সাথে অর্থ বোঝায় না তার সঠিক কারণ সরবরাহ করুন। যদি তা করতে অক্ষম হন, তবে দয়া করে আরও মন্তব্য করা থেকে বিরত থাকুন।
নওফাল

1
আপনার সমাধান জানেন করতে হবে যখন সর্বশেষ ফাইল তৈরি করা হয়েছে। এটি প্রশ্নে ছিল না তাই না, আপনার উত্তর উত্থাপিত প্রশ্নের ভিত্তিতে নয়।
ব্লক ডাউন দ্য পাব
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.