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!