फ़ाइल नाम में तारीख के बाद फ़ाइल संशोधित किया गया था, तो परीक्षण करें


11

मेरे पास YYYYMMDDफ़ाइल नाम में एक फाइल है, जैसे कि

file-name-20151002.txt

मैं यह निर्धारित करना चाहता हूं कि क्या यह फाइल 2015-10-02 के बाद संशोधित की गई थी।

टिप्पणियाँ:

  • मैं इसका आउटपुट देखकर कर सकता हूं ls, लेकिन मुझे पता है कि आउटपुट को पार्स करना lsएक बुरा विचार है।
  • मुझे लगता है की जरूरत नहीं है सब एक विशिष्ट तिथि के बाद दिनांकित फ़ाइलें, सिर्फ परीक्षण करने की जरूरत है एक एक समय में विशिष्ट फ़ाइल।
  • मेरे द्वारा बनाए जाने के बाद मैं उसी तारीख को संशोधित की जा रही फाइल के बारे में चिंतित नहीं हूं। यही है, मैं सिर्फ यह जानना चाहता हूं 20151002कि नाम के साथ इस फ़ाइल को 03 अक्टूबर, 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

उदाहरण आउटपुट:

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 एक्सटेंशन बनाम POSIX की आवश्यकता नहीं होगी।
थॉमस डिकेई

2
तब अपना खुद का संस्करण लिखने के लिए स्वतंत्र महसूस करें। मैं वही लिखता हूं जो मैं लिखना चाहता हूं, न कि वह जो आप मुझे लिखना चाहते हैं .... और जिसमें जीएनयू टूल्स का उपयोग करना शामिल है। IMO, जीएनयू है वास्तविक मानक। और गैर-लिनक्स, गैर-गनु * निक्स बनाम उपयोग में लिनक्स डिस्ट्रोस की सापेक्ष संख्याएं इसका समर्थन करती हैं।
कैस

6
@ कास: थॉमस की टिप्पणी का कठोर जवाब, जो मेरा मानना ​​है, आपके समाधान को बेहतर बनाने के लिए सिर्फ एक सुझाव है ... वास्तविक दुनिया में, "सबसे अधिक मानक संभव" स्क्रिप्ट न केवल एक बोनस है, बल्कि आवश्यक है (या बल्कि, अनिवार्य)। बहुत से स्थान जीएनयू उपकरणों के संस्करण को स्थापित नहीं कर सकते हैं (मुझे लगता है कि 3 अलग-अलग जगहों पर पता चलता है जहां कुछ सिस्टम के नवीनतम संस्करण बैश 2.x हैं और awk इतना पुराना है कि यह बहुत, मूल एक के बहुत करीब है)। इस प्रश्न की आवश्यकताएं शायद "गंभीर" नहीं हैं (लेकिन हो सकती हैं) और अक्सर अन्य लोगों द्वारा तलाश / उपयोग नहीं किया जाता है, लेकिन सामान्य तौर पर, एक पोर्टेबल समाधान होने पर एक +
ओलिवियर दुलैक

मुझे sed: illegal option -- rMacOS 10.9.5 मिल रहा है ।
पीटर ग्रिल

-rsedविस्तारित नियमित अभिव्यक्तियों का उपयोग करने के लिए यह बताने के लिए एक GNU विकल्प है। आप जैसे बुनियादी regexp बढ़ाया बजाय (उपयोग करने के लिए sed स्क्रिप्ट को बदल सकता है sed -e 's/^.*\(2015\)/\1/')लेकिन स्क्रिप्ट के बाकी शायद अभी भी विफल हो जाएगा क्योंकि यह की जीएनयू संस्करणों की आवश्यकता है dateऔर stat, और मुझे नहीं लगता कि Macs (मानक के रूप में उन लोगों के साथ आते हैं, हालांकि वे कर रहे हैं है पूर्व-संकलित पैकेजों में मैक के लिए उपलब्ध)
कैस

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

बैश =~regexp ऑपरेटर बैश सरणी BASH_REMATCH में फ़ाइल नाम के 8 अंक कैप्चर करता है। [[ ]]स्ट्रिंग्स की तुलना करता है, हालांकि आप केवल संख्या के बजाय उनकी तुलना करते हैं [ -gt ]


MacOS 10.9.5 के लिए -cविकल्प प्रतीत नहीं होता है stat
पीटर ग्रिल

मेरी गलती। समतुल्य मालूम पड़ता है stat -f %m -t %F "$file"। क्षमा करें, मैं इसका परीक्षण नहीं कर सकता।
मयूह

statआपकी टिप्पणी के अनुसार परिवर्तन के साथ , चीजें निष्पादित होती हैं लेकिन सभी परीक्षण मामलों के लिए कोई आउटपुट नहीं। लेकिन, क्या "$file" =~ ([0-9]{8}).txt$कर रहा है?
पीटर ग्रिल

यह .txtफ़ाइल नाम के अंत में 8 अंकों की खोज करता है। कोष्ठक ()8 अंक वाले हिस्से को पकड़ता है, और आप इसे पा सकते हैं ${BASH_REMATCH[1]}
मयूह

के साथ अपने बैश does not काम तो if [[=~]]आप बुनियादी कोशिश कर सकते हैं if filedate=$(expr "$file" : '.*-\([0-9]*\).txt')और उसके बाद की जगह ${BASH_REMATCH[1]}से $filedate
मयूह

4

आप ऐसा कर सकते हैं:

  • शेल चर में वर्ष / माह / दिन मान निकालें,
  • एक अस्थायी फ़ाइल बनाएँ
  • का उपयोग touchकमांड (घंटे / मिनट / सेकंड के लिए 0 जोड़ने) अस्थायी फ़ाइल के लिए संशोधन तिथि निर्धारित करने के

क्योंकि आपका सवाल है bash, आप लिनक्स का उपयोग कर रहे हैं। testकार्यक्रम लिनक्स में इस्तेमाल किया (के हिस्से coreutils ) टाइमस्टैम्प तुलना (के लिए एक्सटेंशन नहीं है -ntऔर -ot) में नहीं मिला POSIXtest

POSIX इस बारे में इस तर्क में टिप्पणी करता है test:

नव आविष्कृत या कोर्नशेल से कुछ अतिरिक्त प्राइमरी सशर्त कमांड ( [[]]): s1> s2, s1 <s2, str = pattern, str! = Pattern, f1 -nt f2, f1 -ot f2, के प्रारंभिक प्रस्ताव के रूप में दिखाई दिए। और एफ 1-एफ एफ 2। शेल की सशर्त कमान को हटाए जाने के बाद उन्हें परीक्षण उपयोगिता में आगे नहीं ले जाया गया क्योंकि उन्हें श उपयोगिता के ऐतिहासिक कार्यान्वयन में निर्मित परीक्षण उपयोगिता में शामिल नहीं किया गया है।

उस विस्तार का उपयोग करते हुए, आप तब कर सकते थे

  • उस दिनांक के साथ एक और अस्थायी फ़ाइल बनाएँ जिसकी आप तुलना करना चाहते हैं
  • आपके द्वारा मांगी गई तुलना करने के लिए -ntऑपरेटर का उपयोग करें test

यहाँ एक उदाहरण है। ओपी द्वारा एक स्पष्टीकरण ने प्लेटफ़ॉर्म का उल्लेख किया है, इसलिए कोई statअस्थायी फ़ाइलों के विकल्प के रूप में उपयोग कर सकता है ( OSX और लिनक्स की तुलना करें )

#!/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 अंकों से मेल खाता है। यही कारण है कि की zsh extendedglob बराबर है kshकी {8}([0-9])
  • D: छिपी हुई फाइलें शामिल करें
  • e@...@: फ़ाइलों को और अधिक योग्य बनाने के लिए कुछ पाठ चलाने के लिए स्पष्ट ग्लोब क्वालिफायर। में फ़ाइल पथ पारित किया$REPLY
  • zstat...$mसरणी में YYYYMMDD के रूप में स्वरूपित माइम को पुनः प्राप्त करें ।
  • ${REPLY:t}: फ़ाइल के t tail (basename) का विस्तार करता है।
  • ${(SM)something#pattern}किसी चीज से पार्ट मैचिंग पैटर्न निकालें । उन ( S ubstring खोज) और ( M atched भाग तक विस्तार ) को पैरामीटर विस्तार झंडे कहा जाता है ।SM
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.