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-

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.