ফাইলের নামে তারিখের পরে ফাইলটি সংশোধন করা হয়েছে কিনা তা পরীক্ষা করুন


11

আমার কাছে ফাইলের নামের সাথে একটি ফাইল রয়েছে YYYYMMDDযেমন

file-name-20151002.txt

এই ফাইলটি 2015-10-02 এর পরে সংশোধিত হয়েছে কিনা তা আমি নির্ধারণ করতে চাই ।

মন্তব্য:

  • আমি আউটপুট দেখে এটি করতে পারি ls, তবে আমি জানি যে আউটপুটটির পার্সিং lsকরা একটি খারাপ ধারণা।
  • আমি খুঁজে প্রয়োজন হবে না সব একটি নির্দিষ্ট তারিখের পরে তারিখের ফাইল, শুধু পরীক্ষা প্রয়োজন এক একটি সময়ে নির্দিষ্ট ফাইল।
  • ফাইলটি তৈরি করার পরে একই তারিখে ফাইলটি পরিবর্তন করা হবে বলে আমি উদ্বিগ্ন নই। অর্থাৎ, আমি কেবলমাত্র জানতে চাই যে নামেরযুক্ত এই ফাইলটি 2015100203 অক্টোবর, 2015 বা তার পরে সংশোধিত হয়েছিল।
  • আমি ম্যাকওস 10.9.5 এ আছি।

আগে ওএস অন্তর্ভুক্ত না করার জন্য ক্ষমা চাই।
পিটার গ্রিল

উত্তর:


4

এখানে কয়েকটি সম্ভাব্য উপায় রয়েছে:

  • OSX stat:

    newer () {
    tstamp=${1:${#1}-12:8}
    mtime=$(stat -f "%Sm" -t "%Y%m%d" "$1")
    [[ ${mtime} -le ${tstamp} ]] && printf '%s\n' "$1 : NO: mtime is ${mtime}" || printf '%s\n' "$1 : YES: mtime is ${mtime}"
    }
  • GNU date:

    newer () {
    tstamp=${1:${#1}-12:8}
    mtime=$(date '+%Y%m%d' -r "$1")
    [[ ${mtime} -le ${tstamp} ]] && printf '%s\n' "$1 : NO: mtime is ${mtime}" || printf '%s\n' "$1 : YES: mtime is ${mtime}"
    }
  • zsh কেবল:

    zmodload zsh/stat
    newer () {
    tstamp=${1:${#1}-12:8}
    mtime=$(zstat -F '%Y%m%d' +mtime -- $1)
    [[ ${mtime} -le ${tstamp} ]] && printf '%s\n' "$1 : NO: mtime is ${mtime}" || printf '%s\n' "$1 : YES: mtime is ${mtime}"
    }

ব্যবহার:

আরও নতুন ফাইল

উদাহরণ আউটপুট:

file-name-20150909.txt : YES: mtime is 20151026

অথবা

file-name-20151126.txt : NO: mtime is 20151026

9

নিম্নলিখিত স্ক্রিপ্ট কমান্ড লাইনে নির্দিষ্ট করা সমস্ত ফাইলের তারিখগুলি পরীক্ষা করবে:

এটা গনুহ সংস্করণ প্রয়োজন sed, dateএবংstat

$ cat check-dates.sh 
#! /bin/bash

for f in "$@" ; do
  # get date portion of filename
  fdate=$(basename "$f" .txt | sed -re 's/^.*(2015)/\1/')

  # convert it to seconds since epoch + 1 day
  fsecs=$(echo $(date +%s -d "$fdate") + 86400 | bc )

  # get modified timestamp of file in secs since epoch
  ftimestamp=$(stat -c %Y "$f")

  [ "$ftimestamp" -gt "$fsecs" ] && echo "$f has been modified after $fdate"
done

$ ./check-dates.sh file-name-20151002.txt 
file-name-20151002.txt has been modified after 20151002
$ ls -l file-name-20151002.txt 
-rw-rw-r-- 1 cas cas 0 Oct 26 19:21 file-name-20151002.txt

এখানে একটি সংস্করণ যা অপরিবর্তিত রয়েছে তবে ম্যাক্স (এবং ফ্রিবিএসডি ইত্যাদিতে) কাজ করা উচিত যদি আমি অন-লাইনের ম্যান পৃষ্ঠাগুলি সঠিকভাবে পড়ে থাকি:

#! /bin/bash

for f in "$@" ; do
  # get date portion of filename
  fdate=$(basename "$f" .txt | sed -e 's/^.*\(2015\)/\1/')

  # convert it to seconds since epoch + 1 day
  fsecs=$(echo $(date -j -f %Y%m%d "$fdate" +%s) + 86400 | bc )

  # get modified timestamp of file in secs since epoch
  ftimestamp=$(stat -f %m "$f")

  [ "$ftimestamp" -gt "$fsecs" ] && echo "$f has been modified after $fdate"
done

এর চেয়ে আরও ভাল সমাধান হ'ল পসিক্স বনাম 4-5 এক্সটেনশনের প্রয়োজন নেই।
টমাস ডিকি 26'15

2
আপনার নিজের সংস্করণটি নির্দ্বিধায় লিখুন। আমি যা লিখতে চাই তা লিখি, আপনি যা লিখতে চান তা নয় .... এবং এর মধ্যে সরঞ্জামগুলির GNU সংস্করণ ব্যবহার অন্তর্ভুক্ত রয়েছে। আইএমও, জিএনইউ হ'ল ডি-ফ্যাক্টো স্ট্যান্ডার্ড। এবং লিনাক্সের আপেক্ষিক সংখ্যার ব্যবহারের তুলনায় নন-লিনাক্স, নন-গনু * নিক্সগুলি সমর্থন করে।
কাস

6
@ ক্যাস: থমাসের মন্তব্যের একটি বরং কড়া জবাব যা আমি বিশ্বাস করি, আপনার সমাধানকে উন্নত করার জন্য কেবলমাত্র একটি পরামর্শ ... বাস্তব বিশ্বে "সর্বাধিক মানসম্মত" স্ক্রিপ্ট থাকা কেবল একটি বোনাসই নয়, তবে প্রয়োজনীয় (বা বরং, বাধ্যতামূলক)। অনেক জায়গায় সরঞ্জামের জিএনইউ সংস্করণ ইনস্টল করতে পারে না (আমি 3 টি আলাদা জায়গা জানতে পেরেছি যেখানে কয়েকটি সিস্টেমের সর্বশেষতম ভার্সের ভার্সন 2.x এবং অ্যাজক এত পুরানো এটি মূলটির খুব কাছাকাছি)। এই প্রশ্নের প্রয়োজনগুলি সম্ভবত "সমালোচনামূলক" নয় (তবে এটি হতেও পারে) এবং অন্যান্য লোকেরা প্রায়শই সন্ধান / ব্যবহার করে না তবে সাধারণভাবে একটি বহনযোগ্য সমাধান হ'ল +
অলিভিয়ার ডুলাক

আমি sed: illegal option -- rম্যাকওএস 10.9.5 এর সাথে পাচ্ছি ।
পিটার গ্রিল

-rsedএটি বর্ধিত নিয়মিত এক্সপ্রেশন ব্যবহার করতে বলার জন্য একটি জিএনইউ বিকল্প। আপনি যেমন মৌলিক regexp বাড়ানো বদলে (ব্যবহার করতে sed স্ক্রিপ্ট পরিবর্তন হতে পারে sed -e 's/^.*\(2015\)/\1/')কিন্তু স্ক্রিপ্ট বাকি সম্ভবত এখনো ব্যর্থ হবে কারণ এটি গনুহ সংস্করণ প্রয়োজন dateএবং stat, এবং আমি মনে করি না Macs- এর (আদর্শ তাদের সঙ্গে আসা যদিও তারা না প্রাক কম্পাইল প্যাকেজ Mac এর জন্য উপলব্ধ)
সি এ এস

4

ব্যাশ ব্যবহার এবং statএবং exprসংখ্যার তারিখ পেতে এবং তাদের তুলনা:

#!/bin/bash
for file
do  moddate=$(stat -f %m -t %F "$file") # MacOS stat
    moddate=${moddate//-/} # 20151026
    if filedate=$(expr "$file" : '.*-\([0-9]*\).txt')
    then  if [ $moddate -gt $filedate ]
          then echo "$file: modified $moddate"
          fi
    fi
done

এটি আমার আগের লিনাক্স-নির্দিষ্ট উত্তর ছিল।

#!/bin/bash
for file
do  moddate=$(stat -c %y "$file")
    moddate=${moddate%% *} # 2015-10-26
    moddate=${moddate//-/} # 20151026
    if [[ "$file" =~ ([0-9]{8}).txt$ ]]
    then  if [[ $moddate > ${BASH_REMATCH[1]} ]]
          then echo "$file: modified $moddate"
          fi
    fi
done

ব্যাশ =~রিজেক্সপ অপারেটর ফাইলনামের 8 টি অঙ্ক বাশ অ্যারে BASH_REMATCH এ ক্যাপচার করে। [[ ]]স্ট্রিংগুলির সাথে তুলনা করুন, যদিও আপনি কেবল তাদের পরিবর্তে সংখ্যা হিসাবে তুলনা করেন [ -gt ]


MacOS 10.9.5 এর -cবিকল্প নেই বলে মনে হচ্ছে stat
পিটার গ্রিল

আমার খারাপ। সমান মনে হয় stat -f %m -t %F "$file"। দুঃখিত, আমি এটি পরীক্ষা করতে পারি না।
meuh

statআপনার মন্তব্য অনুসারে পরিবর্তনের সাথে সাথে , জিনিসগুলি কার্যকর হচ্ছে বলে মনে হচ্ছে তবে সমস্ত পরীক্ষার ক্ষেত্রে আউটপুট নেই। কিন্তু, কি "$file" =~ ([0-9]{8}).txt$করছে?
পিটার গ্রিল

এটি .txtফাইলের নামের শেষে 8 টি অঙ্কের সন্ধান করবে। বন্ধনীগুলি ()8 টি সংখ্যার অংশ ক্যাপচার করে এবং আপনি এটি সন্ধান করতে পারেন ${BASH_REMATCH[1]}
meuh

সঙ্গে আপনার ব্যাশ স্বল্পতা কাজ যদি if [[=~]]আপনি মৌলিক চেষ্টা করতে পারেন if filedate=$(expr "$file" : '.*-\([0-9]*\).txt')এবং তারপর প্রতিস্থাপন ${BASH_REMATCH[1]}দ্বারা $filedate
meuh

4

আপনি এটি করতে পারেন:

  • বছর / মাস / দিনের মানগুলি শেল ভেরিয়েবলে বের করুন,
  • একটি অস্থায়ী ফাইল তৈরি করুন
  • touchঅস্থায়ী ফাইলটির পরিবর্তনের তারিখ নির্ধারণ করতে কমান্ডটি (ঘন্টা / মিনিট / সেকেন্ডের জন্য 0 টি যোগ করা) ব্যবহার করুন

কারণ আপনার প্রশ্নটি প্রায় bash, আপনি সম্ভবত লিনাক্স ব্যবহার করছেন। testপ্রোগ্রাম লিনাক্স ব্যবহৃত (অংশ coreutils ) টাইমস্ট্যাম্প তুলনা (জন্য এক্সটেনশন রয়েছে -ntএবং -ot) মধ্যে পাওয়া যায়নি POSIXtest

এ সম্পর্কে যৌক্তিকতায় পসিক্স মন্তব্য করেছেন test:

নতুন আবিষ্কৃত বা কর্নশেল থেকে নেওয়া কিছু অতিরিক্ত প্রাথমিকগুলি শর্তাধীন কমান্ডের অংশ হিসাবে একটি প্রাথমিক প্রস্তাবে উপস্থিত হয়েছিল ( [[]]): এস 1> এস 2, এস 1 <এস 2, আরআর = প্যাটার্ন, স্ট্র! = প্যাটার্ন, এফ 1 -nt এফ 2, এফ 1 -ot f2, এবং এফ 1-এফ এফ 2। শর্ত থেকে শর্তসাপেক্ষে কমান্ড সরানো হলে এগুলি পরীক্ষার ইউটিলিটিতে অগ্রসর করা হয়নি কারণ তারা sh ইউটিলিটির historicalতিহাসিক বাস্তবায়নের ক্ষেত্রে নির্মিত পরীক্ষামূলক ইউটিলিটিতে অন্তর্ভুক্ত করা হয়নি।

সেই এক্সটেনশনটি ব্যবহার করে, আপনি তখন তা করতে পারেন

  • আপনি যে তারিখটির সাথে তুলনা করতে চান তার সাথে একটি অন্য অস্থায়ী ফাইল তৈরি করুন
  • আপনি যে তুলনা চেয়েছিলেন তা করতে -ntঅপারেটরটি ব্যবহার করুন test

এখানে একটি উদাহরণ। ওপির একটি ব্যাখ্যা প্ল্যাটফর্মের কথা উল্লেখ করেছে, সুতরাং কেউ statঅস্থায়ী ফাইলের বিকল্প হিসাবে ব্যবহার করতে পারে ( ওএসএক্স এবং লিনাক্সের তুলনা করুন ):

#!/bin/bash
# inspect each file...

with_tempfile() {
    echo "** with temporary file $name"
    test=$MYTEMP/$name
    touch -t $date $test
    [ $name -nt $test ] && echo "...newer"
}

# alternatively (and this is system-dependent)
with_stat() {
    echo "** with stat command $name"
    stat=$(stat -t "%Y%m%d%H%M" -f "%Sm" $name)
    [ $stat -gt $date ] && echo "...newer"
}

MYTEMP=$(mktemp -d /var/tmp/isnewer.XXXXXX)
trap "rm -rf $MYTEMP" EXIT
for name in file-name-[0-9][0-9]*.txt
do
    if [ -f "$name" ];
    then
            date=${name%%.txt}
            date=${date/file-name-}
            date=${date//-/}2359
            with_tempfile $name
            with_stat $name
    fi
done

অস্থায়ী ফাইল তৈরি করার সময়, trapকমান্ডের সাহায্যে উপেক্ষা করা ফাইলগুলি সরিয়ে ফেলা স্ট্যান্ডার্ড অনুশীলন ।
টমাস ডিকি

আমি MacOS 10.9.5 এ আছি।
পিটার গ্রিল

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

1

অন্য zshপদ্ধতি:

zmodload zsh/stat # best in ~/.zshrc or
zmodload -F zsh/stat +b:zstat # to avoid overriding an eventual
                              # system stat command.
setopt extendedglob # best in ~/.zshrc

ls -ld -- **/*[0-9](#c8)*(De@'zstat -F %Y%m%d -A m +mtime $REPLY &&
  [[ ${(SM)${REPLY:t}#[0-9](#c8)} != $m ]]'@)

এমন ফাইলগুলির প্রতিবেদন করবে যার মধ্যে এমন কিছু রয়েছে যা তাদের নামে টাইমস্ট্যাম্পের মতো দেখাচ্ছে তবে এটি তাদের শেষ পরিবর্তনের সময়ের সাথে সামঞ্জস্য নয়।

zshগ্লোবস এবং ভেরিয়েবলগুলি পরিচালনা করার মতো অপারেটরগুলির আধিক্য রয়েছে। যে কোনও কাজ দ্রুত করা (এবং সাধারণভাবে নির্ভরযোগ্যভাবে করা) খুব সহজ কাজ তবে এগুলির চারপাশে আপনার মাথা পাওয়া যথেষ্ট শক্ত এবং এটি প্রায়শই আমরা কেবলমাত্র লিখনের কোড বলে থাকি তা তৈরি করে (অবৈধ কোডের জন্য শ্রুতিমধুরতা, যদিও বোঝায় যে আপনি ডন 'না কমান্ড প্রম্পটে আপনি একক ব্যবহারের জন্য এটি লেখার সাথে সাথে এটি পড়ার দরকার নেই)

এর মাধ্যমে দ্রুত চালানো:

  • **/pattern(qualifier): গ্লোব কোয়ালিফায়ারের সাথে পুনরাবৃত্ত গ্লোব।
  • [0-9](#c8)8 সংখ্যার সাথে মেলে। এটি ksh's এর সমতুল্য zsh এক্সটেনডগ্লোব {8}([0-9])
  • D: লুকানো ফাইল অন্তর্ভুক্ত
  • e@...@: ফাইলগুলি আরও যোগ্যতার জন্য কিছু পাঠ্য চালানোর জন্য ইভাল গ্লোব কোয়ালিফায়ার। ফাইল পাথ প্রবেশ করেছে$REPLY
  • zstat...$mঅ্যারেতে YYYYMMDD হিসাবে ফর্ম্যাট করা মাইটাইমটি পুনরুদ্ধার করুন ।
  • ${REPLY:t}: ফাইলের টি লেজ (বেস নাম) পর্যন্ত প্রসারিত হয় ।
  • ${(SM)something#pattern}। কোনও কিছু থেকে অংশের মিলের প্যাটার্নটি বের করুন । যারা ( এস অবস্ট্রিং অনুসন্ধান) এবং ( এম আঠা অংশে প্রসারিত ) তাদের প্যারামিটার এক্সপেনশন পতাকা বলেSM
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.