修改docx, xlsx, pptx文档的创建时间和修改时间

在特殊情况下,我们希望修改一个Word文档的创建时间和修改时间,比如说证明文件没有被篡改。(真是高科技作弊=_=)

在文件属性中,有记录创建时间和修改时间。经过复制等操作时,创建时间会发生变化,所以更改这个时间没有任何意义。而修改时间是在文件真正被编辑时才发生改变。修改时间作为文件属性记录在文件系统中,通过touch命令的方式可以直接修改。

snip20170211_1
对于Word文档,Excel文档,PowerPoint文档而言,文件内部也记录了创建时间,修订次数等信息。这些信息是记录在文件内部的。那么如何修改这个属性呢?

snip20170211_2
首先你得明白一点,docx, xlsx, pptx文档其实都是zip压缩文件。如果是doc, xls, ppt文档则需要先另存为成docx, xlsx, pptx文档,才能用以下方法修改。

下面以docx文件为例,

snip20170211_3
snip20170211_4
  1. 将docx文件的后缀名改为zip,并解压zip文件。
  2. 打开docProps文件夹,打开core.xml文件。
  3. 可以看到,dcterms:created对应的值是创建时间,dcterms:modified对应的值是修改时间,时间的格式是yyyy-MM-ddTHH:mm:ssZ。
  4. 修改完成后,保持原有的文件夹结构,压缩成zip文件,修改后缀名为docx,完成!

以下是一个脚本,输入一个文件夹,会修改文件夹下所有docx文件的创建时间和修改时间为2016年6月的某个日期。

#/bin/sh

year="2016"
month="06"

# 输入文件夹目录
echo "请输入目录(路径中不要有空格): "
read dir

# 检测文件夹下是否有doc文件
cd $dir
for file in `ls`
do
if test -d ${dir}"/"${file}
then
continue
fi
extension=${file##*.}
if [ "$extension" == "doc" ]
then
echo "检测到doc文件,请先转换成docx"
exit -1
fi
done

cd $dir
mkdir origin

for file in `ls`
do
# 跳过输入文件夹中的文件夹
if test -d ${dir}"/"${file}
then
continue
fi

# 获取文件后缀
extension=${file##*.}
if [ "$extension" == "docx" ]
then
echo "处理文件:"${file}"..."

# 获取不含后缀的文件名称
filename=${file%%.*}

# 解压docx文件
cd ${dir}
mkdir ${filename}
unzip ${file} -d ${dir}"/"${filename} > /dev/null
mv ${file} ./origin/

# 获取旧时间
coreXml=`cat ${dir}/${filename}/docProps/core.xml`
docCreateTime=$(expr "'${coreXml}'" : '.*(.*).*')
docModifyTime=$(expr "'${coreXml}'" : '.*(.*).*')

# 生成新时间
((day=$RANDOM % 28 + 1))
((dayafter=$day + 1))
if (( $day < 10 )); then
day="0"${day}
fi
if (( $dayafter < 10 )); then
dayafter="0"${dayafter}
fi
((hour=$RANDOM % 16 + 7))
if (( $hour < 10 )); then
hour="0"${hour}
fi
((hourafter=$RANDOM % 16 + 7))
if (( $hourafter < 10 )); then
hourafter="0"${hourafter}
fi
((miniute=$RANDOM % 60))
if (( $miniute < 10 )); then
miniute="0"${miniute}
fi
((miniuteafter=$RANDOM % 60))
if (( $miniuteafter < 10 )); then
miniuteafter="0"${miniuteafter}
fi
((second=$RANDOM % 60))
if (( $second < 10 )); then
second="0"${second}
fi
((secondeafter=$RANDOM % 60))
if (( $secondeafter < 10 )); then secondeafter="0"${secondeafter} fi docCreateTimeNew=${year}"-"${month}"-"${day}"T"${hour}":"${miniute}":"${second}"Z" docModifyTimeNew=${year}"-"${month}"-"${dayafter}"T"${hourafter}":"${miniuteafter}":"${secondeafter}"Z" echo ${docCreateTime}" -> "${docCreateTimeNew}
echo ${docModifyTime}" -> "${docModifyTimeNew}

# 写入新时间
cat ${dir}/${filename}/docProps/core.xml | sed "s/${docCreateTime}/${docCreateTimeNew}/g" | sed "s/${docModifyTime}/${docModifyTimeNew}/g" > ${dir}/${filename}/docProps/core2.xml
rm -f ${dir}/${filename}/docProps/core.xml
mv ${dir}/${filename}/docProps/core2.xml ${dir}/${filename}/docProps/core.xml

# 还原docx文件
cd ${dir}"/"${filename}
zip -r ${dir}"/"${file} ./* > /dev/null
rm -rf ${dir}"/"${filename}

# 用touch修改文件系统中记录的修改时间
touch -t ${year}${month}${dayafter}${hourafter}${miniuteafter}"."${secondeafter} ${dir}"/"${file}
fi
done