以下为一个Mac/Linux 脚本 modify_timestamps.sh,可以修改文件夹及其内容或单个文件的创建和修改时间。

#!/bin/bash

# 修改文件或目录时间戳的脚本
# 使用方法: ./modify_timestamps.sh [选项] <路径> [时间]

# 显示帮助信息
show_help() {
    echo "用法: $0 [选项] <路径> [时间]"
    echo ""
    echo "选项:"
    echo "  -h, --help          显示此帮助信息"
    echo "  -r, --recursive     递归处理目录下的所有文件和子目录"
    echo "  -a, --access        只修改访问时间"
    echo "  -m, --modify        只修改修改时间"
    echo "  -c, --create        修改创建时间(需要debugfs支持)"
    echo "  -f, --force         强制执行,不询问确认"
    echo ""
    echo "时间格式:"
    echo "  YYYY-MM-DD HH:MM:SS  例如: 2024-01-01 12:00:00"
    echo "  如果不指定时间,将使用当前时间"
    echo ""
    echo "示例:"
    echo "  $0 /path/to/file                           # 修改文件为当前时间"
    echo "  $0 /path/to/file '2024-01-01 12:00:00'     # 修改文件为指定时间"
    echo "  $0 -r /path/to/directory                   # 递归修改目录"
    echo "  $0 -m /path/to/file '2024-01-01 12:00:00'  # 只修改修改时间"
    echo "  $0 -c /path/to/file '2024-01-01 12:00:00'  # 修改创建时间"
}

# 默认参数
RECURSIVE=false
ACCESS_ONLY=false
MODIFY_ONLY=false
CREATE_TIME=false
FORCE=false
TARGET_PATH=""
TIMESTAMP=""

# 解析命令行参数
while [[ $# -gt 0 ]]; do
    case $1 in
        -h|--help)
            show_help
            exit 0
            ;;
        -r|--recursive)
            RECURSIVE=true
            shift
            ;;
        -a|--access)
            ACCESS_ONLY=true
            shift
            ;;
        -m|--modify)
            MODIFY_ONLY=true
            shift
            ;;
        -c|--create)
            CREATE_TIME=true
            shift
            ;;
        -f|--force)
            FORCE=true
            shift
            ;;
        -*)
            echo "错误: 未知选项 $1"
            echo "使用 -h 或 --help 查看帮助"
            exit 1
            ;;
        *)
            if [[ -z "$TARGET_PATH" ]]; then
                TARGET_PATH="$1"
            elif [[ -z "$TIMESTAMP" ]]; then
                TIMESTAMP="$1"
            else
                echo "错误: 参数过多"
                exit 1
            fi
            shift
            ;;
    esac
done

# 检查必需参数
if [[ -z "$TARGET_PATH" ]]; then
    echo "错误: 请指定目标路径"
    show_help
    exit 1
fi

# 检查路径是否存在
if [[ ! -e "$TARGET_PATH" ]]; then
    echo "错误: 路径 '$TARGET_PATH' 不存在"
    exit 1
fi

# 如果没有指定时间,使用当前时间
if [[ -z "$TIMESTAMP" ]]; then
    TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
    echo "使用当前时间: $TIMESTAMP"
fi

# 验证时间格式
if ! date -d "$TIMESTAMP" >/dev/null 2>&1; then
    echo "错误: 时间格式无效: $TIMESTAMP"
    echo "请使用格式: YYYY-MM-DD HH:MM:SS"
    exit 1
fi

# 修改创建时间的函数(需要root权限和debugfs)
modify_create_time() {
    local file="$1"
    local timestamp="$2"
    
    # 检查是否有debugfs
    if ! command -v debugfs >/dev/null 2>&1; then
        echo "警告: debugfs 未安装,无法修改创建时间"
        return 1
    fi
    
    # 检查是否有root权限
    if [[ $EUID -ne 0 ]]; then
        echo "警告: 修改创建时间需要root权限"
        return 1
    fi
    
    # 获取文件系统设备
    local device=$(df "$file" | tail -1 | awk '{print $1}')
    local inode=$(stat -c %i "$file")
    
    # 转换时间格式为debugfs需要的格式
    local debug_time=$(date -d "$timestamp" '+%Y%m%d%H%M%S')
    
    echo "正在修改 $file 的创建时间..."
    echo "set_inode_field <$inode> crtime $debug_time" | debugfs -w "$device"
}

# 修改文件时间戳的函数
modify_timestamps() {
    local file="$1"
    local timestamp="$2"
    
    echo "正在处理: $file"
    
    # 构建touch命令参数
    local touch_args=""
    
    if [[ "$ACCESS_ONLY" == true ]]; then
        touch_args="-a"
    elif [[ "$MODIFY_ONLY" == true ]]; then
        touch_args="-m"
    fi
    
    # 修改访问时间和修改时间
    if [[ "$CREATE_TIME" == false ]]; then
        touch $touch_args -d "$timestamp" "$file"
        if [[ $? -eq 0 ]]; then
            echo "✓ 已更新时间戳: $file"
        else
            echo "✗ 更新失败: $file"
        fi
    fi
    
    # 修改创建时间
    if [[ "$CREATE_TIME" == true ]]; then
        modify_create_time "$file" "$timestamp"
    fi
}

# 递归处理目录的函数
process_directory() {
    local dir="$1"
    local timestamp="$2"
    
    # 首先处理目录本身
    modify_timestamps "$dir" "$timestamp"
    
    # 然后处理目录中的内容
    find "$dir" -mindepth 1 -print0 | while IFS= read -r -d '' item; do
        modify_timestamps "$item" "$timestamp"
    done
}

# 确认操作
if [[ "$FORCE" == false ]]; then
    echo "即将修改以下路径的时间戳:"
    echo "路径: $TARGET_PATH"
    echo "时间: $TIMESTAMP"
    echo "递归: $RECURSIVE"
    echo "只修改访问时间: $ACCESS_ONLY"
    echo "只修改修改时间: $MODIFY_ONLY"
    echo "修改创建时间: $CREATE_TIME"
    echo ""
    read -p "确认继续? (y/N): " -n 1 -r
    echo
    if [[ ! $REPLY =~ ^[Yy]$ ]]; then
        echo "操作已取消"
        exit 0
    fi
fi

# 执行操作
echo "开始修改时间戳..."
echo "=================="

if [[ -d "$TARGET_PATH" ]] && [[ "$RECURSIVE" == true ]]; then
    # 递归处理目录
    process_directory "$TARGET_PATH" "$TIMESTAMP"
elif [[ -d "$TARGET_PATH" ]]; then
    # 只处理目录本身
    modify_timestamps "$TARGET_PATH" "$TIMESTAMP"
else
    # 处理单个文件
    modify_timestamps "$TARGET_PATH" "$TIMESTAMP"
fi

echo "=================="
echo "操作完成!"

# 显示结果
echo ""
echo "当前时间戳信息:"
if [[ -d "$TARGET_PATH" ]]; then
    ls -la "$TARGET_PATH"
else
    ls -la "$TARGET_PATH"
fi

这个脚本提供了完整的文件时间戳修改功能,包括以下特性:

主要功能:

  1. 修改单个文件或目录的时间戳
  2. 递归修改目录及其所有内容
  3. 支持修改访问时间、修改时间和创建时间
  4. 灵活的时间格式输入

使用方法:

# 给脚本添加执行权限
chmod +x modify_timestamps.sh

# 基本用法示例
./modify_timestamps.sh /path/to/file                           # 修改为当前时间
./modify_timestamps.sh /path/to/file "2024-01-01 12:00:00"     # 修改为指定时间
./modify_timestamps.sh -r /path/to/directory                   # 递归修改整个目录
./modify_timestamps.sh -m /path/to/file "2024-01-01 12:00:00"  # 只修改修改时间
./modify_timestamps.sh -a /path/to/file "2024-01-01 12:00:00"  # 只修改访问时间
./modify_timestamps.sh -c /path/to/file "2024-01-01 12:00:00"  # 修改创建时间(需要root权限)
./modify_timestamps.sh -f /path/to/file "2024-01-01 12:00:00"  # 强制执行,不询问确认

主要选项:

  • -r, --recursive: 递归处理目录下的所有文件和子目录
  • -a, --access: 只修改访问时间
  • -m, --modify: 只修改修改时间
  • -c, --create: 修改创建时间(需要debugfs和root权限)
  • -f, --force: 强制执行,不询问确认
  • -h, --help: 显示帮助信息

注意事项:

  1. 创建时间修改需要root权限和debugfs工具
  2. 脚本会在执行前显示确认信息(除非使用-f选项)
  3. 支持标准的时间格式:YYYY-MM-DD HH:MM:SS
  4. 如果不指定时间,会使用当前时间

这个脚本应该能满足修改文件和目录时间戳的各种需求。

Q.E.D.


寻门而入,破门而出