I have a file with the name data_extraction_check_03_02_2021.txt. I am trying to get the last three values from the filename which is in the order of date, month and year. After that, I need to concatenate three variables and convert it to a date format so that I can find out how many days are in between that date and current date.

Using the below command, I get the last filename which is the "data_extraction_check_03_02_2021.txt".

 latest_file=$(ls -t | head -n 1)
 echo $latest_file

I am trying to get the date_last, month_last & year_last using the below commands but I get the error "date_last:command not found"

date_last = echo "${latest_file}" | awk -F'[_.]' '{print $4}'
month_last = echo "${latest_file}" | awk -F'[_.]' '{print $5}'
year_last = echo "${latest_file}" | awk -F'[_.]' '{print $6}'

After that, I concatenate the date_last, month_last & year_last using the below command. Not sure how to convert this to a date format.

last_extracted_date=$(echo ${date_last}-${month_last}-${year_last})

5 Answers 5


Your assignment is wrong. There must not be any space characters before or after = and the command substitution $(...) is missing, e.g.

date_last=$(echo "${latest_file}" | awk -F'[_.]' '{print $4}')

Using GNU date you could calculate the number of days like this:

date=$(echo "$latest_file" | awk -F'[._]' '{ print $6 "-" $5 "-" $4 }')
days=$(( ($(date +%s) - $(date +%s -d "$date")) / 86400 ))
echo "$days"

With zsh:

zmodload zsh/datetime

(){ latest=$1; } *_<1-31>_<1-12>_<1970->.txt(om)
strftime -rs t _%d_%m_%Y.txt ${(M)latest%_*_*_*}
strftime 'Date is %F' $t
print Age is $(( (EPOCHSECONDS - t) / 86400 )) days.

Which today (2021-02-22) for me gives:

Date is 2021-02-03
Age is 19 days.

(Besides the syntax errors.)

If the file names are consistent, you can use parameter substitution instead of awk:

$ d="${latest_file: -8:4}-${latest_file: -11:2}-${latest_file: -14:2}"
$ echo "$d"

With bash:

date_last="$(echo $latest_file | cut -d _ -f 4 )"
month_last="$(echo $latest_file | cut -d _ -f 5 )"
year_last="$(echo $latest_file | cut -d _ -f 6 )"
today="$(date +"%F")"
typeset -i old now delta
let now=$(date --date="$today" +"%s")
let old=$(date --date="$iso" +"%s")
let delta=$now-$old
echo Diff is $delta seconds.

With , we can use read to parse the filename


# Split the filename into the "parts" array: split on underscore or dot
IFS="_." read -ra parts <<<"$latest_file"

# Extract the date parts relative to the end of the array ([-1] is the last element)
epoch=$(date -d "${parts[-2]}-${parts[-3]}-${parts[-4]}" "+%s")

# EPOCHSECONDS is a bash builtin variable
days=$(( (EPOCHSECONDS - epoch) / 86400 ))

echo "$days days"    # => "19 days"

Additionally, it is recommended to avoid parsing the output of ls (http://mywiki.wooledge.org/ParsingLs).

    find . -maxdepth 1 -type f -printf "%T@\t%p\0" \
    | sort -z -n \
    | tail -z -n1 \
    | cut -z -f2-

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .