Created
December 26, 2025 13:56
-
-
Save kofj/5a848a2b1ec9f8a8d0616beff372337f to your computer and use it in GitHub Desktop.
修复 iOS 备份导出照片时间
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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