Sign up ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It's 100% free, no registration required.

I have a files named with YYYYMMDD in the file name, such as

file-name-20151002.txt

I want to determine if this file was modified after 2015-10-02.

Notes:

  • I can do this by looking at the output of ls, but I know that parsing the output of ls is a bad idea.
  • I don't need to find all files dated after a specific date, just need to test one specific file at a time.
  • I am not conceded about the file being modified on the same date after I created it. That is, I just want to know if this file with 20151002 in the name was modified on Oct 03, 2015 or later.
share|improve this question

5 Answers 5

The following script will check the dates of all files specified on the command line:

$ 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
share|improve this answer
    
An even better solution would be one not requiring 4-5 extensions vs POSIX. – Thomas Dickey 22 hours ago
1  
Feel free to write your own version, then. I write what I want to write, not what you want me to write....and that includes using GNU versions of tools. IMO, GNU IS the de-facto standard. and the relative numbers of linux distros in use vs non-linux, non-gnu *nixes supports that. – cas 22 hours ago
5  
@cas: a rather harsh reply to Thomas's comment which was, I believe, just a suggestion to improve your solution... In the real world, having "the most standard possible" script is not only a bonus, but is necessary (or rather, mandatory). Many places can't install the GNU version of tools (I happen to know 3 different places where some system's latest vers of bash are 2.x and awk is so old it is very, very close to the original one). This question's needs is probably not "critical" (but could be) and also not often seeked/used by other people, but in general, having a portable solution is a + – Olivier Dulac 19 hours ago

Here's another way with GNU date/bash (use it as newer filename):

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}"
}

output:

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

or

file-name-20151126.txt : NO : mtime is 20151026
share|improve this answer

You could do this:

  • extract the year/month/day values into a shell variable,
  • create a temporary file
  • use the touch command (adding 0s for hour/minute/second) to set the modification date for the temporary file

Because your question is about bash, you likely are using Linux. The test program used in Linux (part of coreutils) has extensions for timestamp comparison (-nt and -ot) not found in POSIX test.

POSIX comments about this in the rationale for test:

Some additional primaries newly invented or from the KornShell appeared in an early proposal as part of the conditional command ([[]]): s1 > s2, s1 < s2, str = pattern, str != pattern, f1 -nt f2, f1 -ot f2, and f1 -ef f2. They were not carried forward into the test utility when the conditional command was removed from the shell because they have not been included in the test utility built into historical implementations of the sh utility.

Using that extension, you could then

  • create another temporary file with the date you want to compare against
  • use the -nt operator in test to make the comparison you asked for.
share|improve this answer
    
...and then remove the temporary file – don_crissti 17 hours ago
    
When creating temporary files, it is standard practice to remove overlooked files with a trap command. – Thomas Dickey 10 hours ago

Using bash and stat to get the dates as strings and comparing them:

#!/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

The bash =~ regexp operator captures the 8 digits of the filename into bash array BASH_REMATCH. [[ ]] compares the strings, though you simply compare them as numbers instead in [ -gt ].

share|improve this answer

Directly capturing the YYYYMMDD format (8 digits) in the name with a regex:

[[ $a =~ ([0-9]{8}) ]]

And using stat for modification date (in seconds after epoch):

#!/bin/bash

if [[ $1 =~ ([0-9]{8}) ]]; then

    namedate="$(date -ud "${BASH_REMATCH[1]}" "+%s")"
            correct=$?
            if [[ $correct != 0 ]]; then
                echo "Date in the file name $1 seems incorrect"
                exit 2
            fi

    modifdate="$(stat -c '+%Y' $1)"
            correct=$?
            if [[ $correct != 0 ]]; then
                echo "File time for file $1 could not be found"
                exit 3
            fi

    if (( $modifdate > $namedate )); then
                echo "File was modified after the date in its name."
    else
                echo "File has not been modified"
    fi
fi

Please be aware of:

  1. Call the script with the file name: ./script.sh file-name-20151002.txt
  2. The dates are understood as UTC by the stat from the OS.
  3. I do not know in what format are the dates in the file name.
  4. I assumed they were also in UTC, that's why the -u option in date.
  5. The tests do not take into account "Daylight saving time" effects.
  6. Or, local date/time changes.
  7. The script does just a basic check for date in the name (and warns).
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.