Skip to content

Instantly share code, notes, and snippets.

@kofj
Created December 26, 2025 13:56
Show Gist options
  • Select an option

  • Save kofj/5a848a2b1ec9f8a8d0616beff372337f to your computer and use it in GitHub Desktop.

Select an option

Save kofj/5a848a2b1ec9f8a8d0616beff372337f to your computer and use it in GitHub Desktop.
修复 iOS 备份导出照片时间
#!/bin/bash
# 设置文件创建和修改时间的脚本
# 从文件名提取时间信息并应用到文件
# 支持的格式:YYYY_MM_DD_HH_MM_SS_IMG_xxxx.JPG/HEIC/MOV/PNG/MP4/GIF
# 默认值
DRY_RUN=false
VERBOSE=false
# 显示帮助信息
show_help() {
echo "用法: $0 [选项] <目录>"
echo "选项:"
echo " -h, --help 显示此帮助信息"
echo " -n, --dryrun 预览模式,显示将要执行的操作但不实际修改文件"
echo " -v, --verbose 详细输出模式"
echo "示例:"
echo " $0 tinvee # 执行操作"
echo " $0 --dryrun tinvee # 预览模式"
echo " $0 --dryrun --verbose tinvee # 详细预览模式"
}
# 解析命令行参数
while [[ $# -gt 0 ]]; do
case $1 in
-h|--help)
show_help
exit 0
;;
-n|--dryrun|--dry-run)
DRY_RUN=true
shift
;;
-v|--verbose)
VERBOSE=true
shift
;;
-*)
echo "错误:未知选项 $1"
echo "使用 -h 或 --help 查看帮助信息"
exit 1
;;
*)
if [ -z "$TARGET_DIR" ]; then
TARGET_DIR="$1"
else
echo "错误:只能指定一个目录"
exit 1
fi
shift
;;
esac
done
# 检查是否提供了目录参数
if [ -z "$TARGET_DIR" ]; then
echo "错误:请提供目录参数"
show_help
exit 1
fi
# 检查目录是否存在
if [ ! -d "$TARGET_DIR" ]; then
echo "错误:目录 '$TARGET_DIR' 不存在"
exit 1
fi
# 计数器
processed=0
skipped=0
errors=0
# 显示运行模式
if [ "$DRY_RUN" = true ]; then
echo "*** 预览模式 - 不会实际修改文件 ***"
else
echo "*** 执行模式 - 将修改文件时间戳 ***"
fi
if [ "$VERBOSE" = true ]; then
echo "*** 详细输出模式 ***"
fi
echo "开始处理目录: $TARGET_DIR"
echo "----------------------------------------"
# 遍历目录中的文件
for file in "$TARGET_DIR"/*; do
# 检查是否是文件
if [ ! -f "$file" ]; then
continue
fi
# 获取文件名(不包含路径)
filename=$(basename "$file")
# 检查文件名格式是否符合要求(YYYY_MM_DD_HH_MM_SS_...)
# 将文件转为小写进行匹配
filename_lower=$(echo "$filename" | tr '[:upper:]' '[:lower:]')
if [[ ! $filename_lower =~ ^([0-9]{4})_([0-9]{2})_([0-9]{2})_([0-9]{2})_([0-9]{2})_([0-9]{2})_.*\.(jpg|jpeg|heic|mov|png|mp4|gif)$ ]]; then
if [ "$VERBOSE" = true ] || [ "$DRY_RUN" = true ]; then
echo "跳过文件名格式不符合的文件: $filename"
fi
((skipped++))
continue
fi
# 提取时间信息
year="${BASH_REMATCH[1]}"
month="${BASH_REMATCH[2]}"
day="${BASH_REMATCH[3]}"
hour="${BASH_REMATCH[4]}"
minute="${BASH_REMATCH[5]}"
second="${BASH_REMATCH[6]}"
# 构建时间字符串格式为 MM/DD/YYYY HH:MM:SS
date_string="$month/$day/$year $hour:$minute:$second"
# 验证日期时间的有效性
has_error=false
# 检查月份
if [ "$month" -lt 1 ] || [ "$month" -gt 12 ]; then
echo "错误:无效的月份 ($month) 在文件 $filename"
has_error=true
fi
# 检查日期
if [ "$day" -lt 1 ] || [ "$day" -gt 31 ]; then
echo "错误:无效的日期 ($day) 在文件 $filename"
has_error=true
fi
# 检查小时
if [ "$hour" -lt 0 ] || [ "$hour" -gt 23 ]; then
echo "错误:无效的小时 ($hour) 在文件 $filename"
has_error=true
fi
# 检查分钟
if [ "$minute" -lt 0 ] || [ "$minute" -gt 59 ]; then
echo "错误:无效的分钟 ($minute) 在文件 $filename"
has_error=true
fi
# 检查秒钟
if [ "$second" -lt 0 ] || [ "$second" -gt 59 ]; then
echo "错误:无效的秒钟 ($second) 在文件 $filename"
has_error=true
fi
# 如果有错误,跳过该文件
if [ "$has_error" = true ]; then
((errors++))
continue
fi
# 显示将要执行的操作
if [ "$DRY_RUN" = true ]; then
echo "[预览] 将处理: $filename -> 设置时间为: $date_string"
# 显示要执行的命令
if [ "$VERBOSE" = true ]; then
echo " [预览] 执行命令: SetFile -d \"$date_string\" -m \"$date_string\" \"$file\""
fi
else
echo "处理文件: $filename -> 设置时间为: $date_string"
# 在详细模式下显示要执行的命令
if [ "$VERBOSE" = true ]; then
echo " 执行命令: SetFile -d \"$date_string\" -m \"$date_string\" \"$file\""
fi
fi
# 执行实际的文件时间设置(非预览模式)
if [ "$DRY_RUN" = false ]; then
# 使用 SetFile 命令(macOS 特有)
# -d 参数设置创建时间
# -m 参数设置修改时间
if SetFile -d "$date_string" -m "$date_string" "$file"; then
echo "✓ 成功设置: $filename"
((processed++))
else
echo "✗ 失败: $filename"
((errors++))
fi
else
# 预览模式下,只计数
((processed++))
fi
done
echo "----------------------------------------"
echo "处理完成!"
# 根据模式显示不同信息
if [ "$DRY_RUN" = true ]; then
echo "预览结果统计:"
else
echo "处理结果统计:"
fi
echo "将要处理/已处理的文件数: $processed"
echo "跳过的文件数: $skipped"
echo "错误的文件数: $errors"
# 显示最终提示
if [ "$DRY_RUN" = true ]; then
echo ""
echo "*** 这是预览模式,没有实际修改文件 ***"
echo "如果结果符合预期,请去掉 --dryrun 参数重新执行"
elif [ $errors -eq 0 ]; then
echo ""
echo "✓ 所有文件处理成功!"
else
echo ""
echo "✗ 有 $errors 个文件处理失败,请检查错误信息。"
exit 1
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment