使用 bash 更新文件 date/time 戳记
use bash to update a files date/time stamp
我想使用此代码片段更新使用文件名的文件日期和时间戳:
示例文件名:
2009.07.04-03.42.01.mov
2019.06.08-01.12.08.mov
我收到以下错误消息“操作“运行 Shell 脚本”遇到错误:“触摸:超出范围或非法时间规范:[[CC]YY]MMDDhhmm[。党卫军]”
我该如何修改这段代码?
for if in "$@"
do
date_Time=$(echo "$if" | awk '{ print substr( [=13=], 1, length([=13=])-7 ) }' | sed 's/\.//g' | sed 's/-//')
touch -t "$date_Time" "$if"
done
更新(01/05/2022):......
我还希望代码适用于以下文件名格式...
以及没有时间信息的文件名(时间默认为中午 12 点):
2009.07.04.mov
2019.06.08.mov
以及带有描述信息的文件名:
2009.07.04-file-description.mov
2019.06.08-video-file info.mp4
2019.06.08-video-old-codec.avi
错误消息表明您传入的文件名与您的示例不匹配。也许修改您的代码以在根本没有文件的情况下显示错误消息,并在传递带有目录名称的文件时删除路径。
顺便说一句,if
是一个关键字,因此您可能不想将它用作变量名,即使它是可能的。
#!/bin/sh
if [ $# == 0 ]; then
echo "Syntax: [=10=] files ..." >&2
exit 1
fi
for f in "$@"
do
date_Time=$(echo "$f" | awk '{ sub(/.*\//, ""); gsub(/[^0-9]+/, ""); print substr( [=10=], 1, length([=10=])-7 ) }')
touch -t "$date_Time" "$if"
done
另请注意我是如何分解出 sed
脚本的; awk 可以做所有 sed
可以做的事情,所以我在主脚本中包含了最后的转换。 (顺便说一句,sed 's/[-.]//g'
可以同时完成这两项工作;或者您可以通过一次 sed
调用来完成 sed -e 's/\.//' -e 's/-//'
。)
如果您使用 Bash,您可以进一步简化:
#!/bin/bash
if [ $# == 0 ]; then
echo "Syntax: [=11=] 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 "[=11=]: $f did not seem to contain a valid date ($dt)" >&2;;
esac
done
另请注意代码现在如何在无法从文件名中准确提取 14 位数字时发出警告。 parameter expansions 有点笨拙,但比分别对每个文件名调用 Awk 更有效(而且 Awk 代码也不是特别优雅或健壮)。
快速小巧的bash函数
setDateFileFromName() {
local _file _dtime
for _file ;do
_dtime="${_file%.*.mov}"
_dtime="${_dtime##*/}"
touch -t ${_dtime//[!0-9]/} "$_file"
done
}
然后
setDateFileFromName /path/to store dir/????.??.??-??.??.??.mov
备注。这适用于格式为您的样本的文件名。文件名格式的任何更改都会破坏此!
我想使用此代码片段更新使用文件名的文件日期和时间戳:
示例文件名:
2009.07.04-03.42.01.mov
2019.06.08-01.12.08.mov
我收到以下错误消息“操作“运行 Shell 脚本”遇到错误:“触摸:超出范围或非法时间规范:[[CC]YY]MMDDhhmm[。党卫军]”
我该如何修改这段代码?
for if in "$@"
do
date_Time=$(echo "$if" | awk '{ print substr( [=13=], 1, length([=13=])-7 ) }' | sed 's/\.//g' | sed 's/-//')
touch -t "$date_Time" "$if"
done
更新(01/05/2022):...... 我还希望代码适用于以下文件名格式...
以及没有时间信息的文件名(时间默认为中午 12 点):
2009.07.04.mov
2019.06.08.mov
以及带有描述信息的文件名:
2009.07.04-file-description.mov
2019.06.08-video-file info.mp4
2019.06.08-video-old-codec.avi
错误消息表明您传入的文件名与您的示例不匹配。也许修改您的代码以在根本没有文件的情况下显示错误消息,并在传递带有目录名称的文件时删除路径。
顺便说一句,if
是一个关键字,因此您可能不想将它用作变量名,即使它是可能的。
#!/bin/sh
if [ $# == 0 ]; then
echo "Syntax: [=10=] files ..." >&2
exit 1
fi
for f in "$@"
do
date_Time=$(echo "$f" | awk '{ sub(/.*\//, ""); gsub(/[^0-9]+/, ""); print substr( [=10=], 1, length([=10=])-7 ) }')
touch -t "$date_Time" "$if"
done
另请注意我是如何分解出 sed
脚本的; awk 可以做所有 sed
可以做的事情,所以我在主脚本中包含了最后的转换。 (顺便说一句,sed 's/[-.]//g'
可以同时完成这两项工作;或者您可以通过一次 sed
调用来完成 sed -e 's/\.//' -e 's/-//'
。)
如果您使用 Bash,您可以进一步简化:
#!/bin/bash
if [ $# == 0 ]; then
echo "Syntax: [=11=] 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 "[=11=]: $f did not seem to contain a valid date ($dt)" >&2;;
esac
done
另请注意代码现在如何在无法从文件名中准确提取 14 位数字时发出警告。 parameter expansions 有点笨拙,但比分别对每个文件名调用 Awk 更有效(而且 Awk 代码也不是特别优雅或健壮)。
快速小巧的bash函数
setDateFileFromName() {
local _file _dtime
for _file ;do
_dtime="${_file%.*.mov}"
_dtime="${_dtime##*/}"
touch -t ${_dtime//[!0-9]/} "$_file"
done
}
然后
setDateFileFromName /path/to store dir/????.??.??-??.??.??.mov
备注。这适用于格式为您的样本的文件名。文件名格式的任何更改都会破坏此!