Home > OS >  use bash to update a files date/time stamp
use bash to update a files date/time stamp

Time:01-04

I would like to use this code snippet to update a files date and time stamp using there file name:

Example file names:

2009.07.04-03.42.01.mov
2019.06.08-01.12.08.mov

I get the following error "The action “Run Shell Script” encountered an error: “touch: out of range or illegal time specification: [[CC]YY]MMDDhhmm[.SS]”

How would I modify this code snippet?

for if in "$@"
do
 date_Time=$(echo "$if" | awk '{ print substr( $0, 1, length($0)-7 ) }' | sed 's/\.//g' | sed 's/-//')
  touch -t "$date_Time" "$if"
done

CodePudding user response:

The error message suggests that you passed in file names which do not match your examples. Perhaps modify your code to display an error message if it is called with no files at all, and remove the path if it is passed files with directory names.

As an aside, if is a keyword, so you probably don't want to use it as a variable name, even though it is possible.

#!/bin/sh

if [ $# == 0 ]; then
    echo "Syntax: $0 files ..." >&2
    exit 1
fi

for f in "$@"
do
    date_Time=$(echo "$f" | awk '{ sub(/.*\//, ""); gsub(/[^0-9] /, ""); print substr( $0, 1, length($0)-7 ) }')
    touch -t "$date_Time" "$if"
done

Notice also how I factored out the sed scripts; Awk can do everything sed can do, so I included the final transformation in the main script. (As an aside, sed 's/[-.]//g' would do both in one go; or you could do sed -e 's/\.//' -e 's/-//' with a single sed invocation.)

If you use Bash, you could simplify this further:

#!/bin/bash

if [ $# == 0 ]; then
    echo "Syntax: $0 files ..." >&2
    exit 1
fi

for f in "$@"
do
    base=${f##*/}
    dt=${base//[!0-9]/}
    dt=${dt:0:12}
    case $dt in
      [0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9])
         touch -t "$dt" "$f";;
      *) echo "$0: $f did not seem to contain a valid date ($dt)" >&2;;
    esac
done

Notice also how the code now warns if it cannot extract exactly 14 digits from the file name. The parameter expansions are somewhat clumsy but a lot more efficient than calling Awk on each file name separately (and the Awk code wasn't particularly elegant or robust either anyway).

CodePudding user response:

Quick and small bash function

setDateFileFromName() {
    local _file _dtime
    for _file ;do
        _dtime="${_file%.*.mov}"
        _dtime="${_dtime##*/}"
        touch -t ${_dtime//[!0-9]/} "$_file"
    done
}

Then

setDateFileFromName /path/to store dir/????.??.??-??.??.??.mov

Remark. This work with filenames formated as your sample. Any change in filename format will break this!

  •  Tags:  
  • Related