1

I will be receiving data files in a Linux directory.

I need to validate that the file names follow the following pattern "NNN-YYYYMMDD-NNNNNNNNN.pdf" where

  • NNN stands for numeric value (0-9).
  • "YYYYMMDD" stands for valid date. YYYY is the year, MM is the month (between 1-12) and DD is the day of the month (can have values between 01 to 31 depending on the month).
  • NNNNNNNN is a numeric number (i.e. only 0-9 allowed).

What utility (SED, AWK etc.) and how should I use to validate the file name.

  • you are looking for some manual started script, which validates a string? – Jaleks Jul 7 '17 at 19:44
  • You can do this using grep – ryekayo Jul 7 '17 at 19:45
  • Please show me how. – AlluSingh Jul 7 '17 at 19:47
  • Can you give me a sample file that you are expecting? Please post it to your question.. – ryekayo Jul 7 '17 at 19:49
  • Does the year have to be the current year? Or current or prior? Or any from 0000 to 9999? – Jeff Schaller Jul 7 '17 at 19:52
2

This tests every file in the current directory, using bash's [[ operator, against the pattern:

  • start of string ^
  • 3 digits
  • -
  • 8 digits
  • -
  • 9 digits
  • .pdf
  • end of string $
  • that the middle 8 digits evaluate to a valid date according to GNU date

You can adjust the assumptions above easily enough.

for f in *
do
  [[ $f =~ ^([0-9][0-9][0-9])-([0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9])-([0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]).pdf$ ]] && 
  date -d ${BASH_REMATCH[2]} &>/dev/null && 
  echo Valid: "$f"
done
  • nicer one, if year, month and day really always have the correct number count, maybe still remove the accidentally .pdf at the end :-) – Jaleks Jul 7 '17 at 20:25
  • Thanks a lot. I changed it to: for f in "123-20170730-123456789.pdf" do [[ $f =~ ^([0-9]{3})-([0-9]{8})-([0-9]{9}).pdf$ ]] && date -d ${BASH_REMATCH[2]} &>/dev/null if [ $? -eq 0 ] then echo "Good File" else echo "Bad File" fi; done – AlluSingh Jul 7 '17 at 22:07
  • I have two (2) questions. Question 1: What is "~" in the expression. Question 2: Why does the following statement not work: for f in "123-20170730-123456789.pdf" do echo $f | grep '^([0-9]{3}-([0-9]{8})-([0-9]{9}).pdf$' &> /dev/null if [ $? -eq 0 ] then echo "Good File" else echo "Bad File" fi; done – AlluSingh Jul 7 '17 at 22:11
  • @AlluSingh (1): Match a regex … (2) because you need to use *Extended" regex syntax and because you have not closed the first (. This do work: echo "123-20170730-123456789.pdf" | grep -E '^([0-9]{3})-([0-9]{8})-([0-9]{9}).pdf$' – Arrow Jul 7 '17 at 22:26
1

sounds like:

TOCHECK=( "01-20170228-12345678" "012-20170230-012345678" "01-20170228-12345678" "123-20170730-012345678" )

for CHECK in $(seq 0 $(( ${#TOCHECK[@]}-1 )) ); do
    PARTS=( $(echo ${TOCHECK[$CHECK]} | sed "s/-/ /g")   )   
    echo -ne "\nchecking "
    echo "\"${PARTS[@]}\""
    echo "\"${PARTS[0]}\""
    echo "\"${PARTS[1]}\""
    echo "\"${PARTS[2]}\""

    if echo ${PARTS[0]} | grep "[0-9]\{3\}" ; then
        echo first part ok
    fi

    if echo ${PARTS[2]} | grep "[0-9]\{9\}" ; then
        echo last part ok
    fi  

    date --date="${PARTS[1]}"
    RES=$?
    echo $RES
    if [ 0$RES -eq 0 ]; then
        echo date OK
    fi  
done

(just some conceptual idea, of course to be modified)

1

It's not enough to use regexps. The validation is 2 steps: regexp matching and date validation. Here's a Python implementation:

from __future__ import print_function
import sys 
import re
import datetime

def validate(filename):
    match = re.match(r"[0-9]{3}-([0-9]{8})-[0-9]{8}\.pdf", filename)
    if not match:
        return False
    datestr = match.group(1)
    try:
        datetime.date(int(datestr[:4]), int(datestr[4:6]), int(datestr[6:8]))
    except ValueError:
        return False
    else:
        return True

if __name__ == "__main__":
    if validate(sys.argv[1]):
        print(":-)")
        sys.exit(0)
    else:
        print(":-(")
        sys.exit(1)

Usage: python validate.py FILE

One can probably use grep and date to do the same.

1

One basic solution, using grep. Doesn't do the detailed date checking aspect, instead merely checks it's numeric.

if ls|grep -vE '^[0-9]{3}-[0-9]{8}-[0-9]{8}\.pdf$'; then
    echo some bogus files found
else
    echo all good
fi

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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