如何自动提取Git指定时间段的修改文件?Win/Linux双平台解决方案

直接上干货

linux脚本

shell 复制代码
#!/bin/bash

# ==============================================
# 脚本名称:git_changes_extractor.sh
# 功能:提取指定时间范围内的Git修改文件到目标目录
# 创建日期:2023-12-27
# ==============================================

# 项目根目录(根据您提供的路径)
# 这是要提取Git变更文件的源项目目录
PROJECT_ROOT="/media/consola/test/coding/company/bussness/gui_yang/ueba/base/project/ueba"

# 目标目录(要求的路径)
# 提取的文件将被复制到这个目录中
TARGET_DIR="/media/consola/test/coding/study/202512/EasyUI-Jquery/note/2025-12-26/git提取要提交的代码"

# 确保目标目录存在
# -p 参数:如果目录不存在则创建,如果已存在也不会报错
mkdir -p "$TARGET_DIR"

# 进入项目根目录执行 Git 操作
# 使用cd命令切换到项目目录,如果切换失败则输出错误信息并退出脚本
cd "$PROJECT_ROOT" || { 
    echo "❌ 项目路径不存在: $PROJECT_ROOT" 
    exit 1 
}

# ==============================================
# Git日志提取和处理流程
# ==============================================

# 提取修改文件列表(已过滤指定路径,保留原始文件路径)
# 使用git log命令获取2025年12月25日到12月26日之间的提交记录
git log --since="2025-12-25" --until="2025-12-26" \
  --pretty=format:'%ad | %an |' --date=format:'%Y-%m-%d %H:%M:%S' \
  --name-only | \
  # 过滤掉不需要的目录:排除linkgraph目录下的文件
  grep -v '^link_data_knowledge/src/main/resources/static/linkgraph/' | \
  # 使用awk处理输出:
  # -F'|' 设置字段分隔符为竖线
  # NF==1 表示只有一列(即文件路径行,因为提交信息行有竖线分隔符)
  # $1!="" 排除空行
  # 最终输出文件路径
  awk -F'|' 'NF==1 && $1!="" {print $1}' | \
  # 排序并去重:确保相同的文件路径只出现一次
  sort | uniq | \
  # 逐行读取处理每个文件路径
  while read file_path; do
    # 构建源文件和目标文件路径
    # 源文件:项目根目录 + 文件相对路径
    src_file="$PROJECT_ROOT/$file_path"
    # 目标文件:目标目录 + 文件相对路径
    dest_file="$TARGET_DIR/$file_path"

    # 创建目标目录(如果不存在)
    # dirname命令提取文件路径中的目录部分
    # mkdir -p 递归创建目录结构
    mkdir -p "$(dirname "$dest_file")"

    # 复制文件(跳过不存在的文件)
    # -f 参数检查是否为普通文件(排除目录、符号链接等)
    if [ -f "$src_file" ]; then
      # 使用cp命令复制文件到目标位置
      cp "$src_file" "$dest_file"
      echo "✅ 已复制: $file_path"
    else
      # 如果源文件不存在,输出警告信息
      echo "⚠️ 跳过 (不存在): $file_path"
    fi
  done

# ==============================================
# 结果统计和输出
# ==============================================

# 统计复制的文件数量
# find命令:在目标目录中查找所有普通文件
# wc -l:统计行数(即文件数量)
file_count=$(find "$TARGET_DIR" -type f | wc -l)

# 输出完成信息
echo -e "\n🎉 复制完成! 共复制 $file_count 个文件"
echo "📁 目标目录: $TARGET_DIR"

# ==============================================
# 使用说明:
# 1. 修改PROJECT_ROOT和TARGET_DIR变量为实际路径
# 2. 修改--since和--until参数为需要的时间范围
# 3. 根据需要调整grep过滤规则
# 4. 给脚本添加执行权限:chmod +x git_changes_extractor.sh
# 5. 运行脚本:./git_changes_extractor.sh
# ==============================================

win脚本(CMD命令执行)

因为 powershell执行的ps1 文件环境有点复杂没有写,cmd够用了

shell 复制代码
@echo off
:: 关闭命令回显,使脚本运行时不会显示执行的命令

chcp 65001 >nul 2>&1
:: 将控制台代码页设置为UTF-8(65001),以支持中文字符显示
:: >nul 2>&1 表示将标准输出和错误输出都重定向到空设备,不显示任何信息

setlocal enabledelayedexpansion
:: 启用延迟环境变量扩展,允许在代码块内使用!var!访问变量的动态值

:: ==============================================
:: 配置参数部分
:: ==============================================

:: 项目根目录 - 要提取Git变更文件的源项目路径
set "PROJECT_ROOT=E:\WorkSpace\ZhongJinHuiAn\project\GuiYang\ueba"

:: 目标目录 - 提取的文件将被复制到这个目录
set "TARGET_DIR=C:\Users\consola\Downloads\TestJpg\TestJpg\20251226\temp01"

:: 开始日期 - Git日志查询的起始日期
set "START_DATE=2025-12-25"

:: 结束日期 - Git日志查询的截止日期
set "END_DATE=2025-12-26"

:: 排除路径模式 - 匹配这个模式的文件路径将被跳过(注意:反斜杠要转义)
:: 这里排除了linkgraph目录下的所有文件
set "excludePattern=link_data_knowledge\\src\\main\\resources\\static\\linkgraph\\"

:: ==============================================
:: 目录准备部分
:: ==============================================

:: 进入项目目录
cd /d "%PROJECT_ROOT%" || (
    :: 如果目录切换失败,显示错误信息并暂停
    echo ❌ 无法进入项目目录: %PROJECT_ROOT%
    pause
    exit /b 1  :: 退出脚本,返回错误代码1
)

:: 创建目标目录(如果不存在)
if not exist "%TARGET_DIR%" md "%TARGET_DIR%"

:: ==============================================
:: Git日志提取部分
:: ==============================================

echo 🕒 正在提取修改的文件...
echo.

:: 创建一个临时文件来存储Git命令的输出
:: %TEMP% 是Windows环境变量,指向临时文件夹
:: %RANDOM% 生成随机数,确保文件名唯一
set "TEMP_FILE=%TEMP%\git_whatchanged_%RANDOM%.txt"

:: 执行git whatchanged命令获取修改文件列表
:: --since 和 --until: 指定时间范围
:: --name-only: 只显示文件名,不显示提交信息
:: --oneline: 每个提交显示在一行中
:: > "%TEMP_FILE%": 将输出重定向到临时文件
:: 2>nul: 将错误信息重定向到空设备,不显示
git whatchanged --since="%START_DATE%" --until="%END_DATE%" --name-only --oneline > "%TEMP_FILE%" 2>nul

:: ==============================================
:: 文件处理部分
:: ==============================================

:: 初始化计数器
set "fileCount=0"      :: 找到的文件总数(去重后)
set "filesCopied=0"    :: 成功复制的文件数

echo 📋 找到的修改文件:
echo =========================================

:: 使用for循环逐行读取临时文件内容
:: /f "tokens=*": 读取整行内容
:: %%a: 循环变量,代表当前行
for /f "tokens=*" %%a in ('type "%TEMP_FILE%" ^| findstr /v "^[a-f0-9][a-f0-9]*\s" ^| findstr /v "^$" ^| findstr /v "^:"') do (
    :: 获取文件路径
    set "filePath=%%a"
    
    :: 将路径中的正斜杠(/)转换为反斜杠(\),适应Windows路径格式
    set "filePath=!filePath:/=\!"
    
    :: 检查文件路径是否为空
    if not "!filePath!"=="" (
        :: 去重检查:使用动态变量名确保每个文件只处理一次
        :: FILE_!filePath! 是一个动态命名的变量,如果未定义,则说明文件未处理过
        if not defined FILE_!filePath! (
            :: 标记文件已处理
            set "FILE_!filePath!=1"
            
            :: 排除检查:如果文件路径包含排除模式,则跳过
            :: findstr /i: 不区分大小写搜索
            :: >nul: 将输出重定向到空设备
            echo !filePath! | findstr /i "!excludePattern!" >nul
            
            :: errorlevel 1 表示没有匹配到排除模式
            if errorlevel 1 (
                :: 文件不在排除路径中
                if exist "!filePath!" (
                    :: 显示文件路径
                    echo 📄 !filePath!
                    :: 文件计数加1
                    set /a fileCount+=1
                    
                    :: 构建目标文件路径
                    set "destPath=%TARGET_DIR%\!filePath!"
                    
                    :: 提取目标文件所在目录
                    :: %%~dpF: 提取完整路径的驱动器和目录部分
                    for %%F in ("!destPath!") do set "destDir=%%~dpF"
                    
                    :: 创建目标目录(如果不存在)
                    if not exist "!destDir!" md "!destDir!" >nul 2>&1
                    
                    :: 复制文件
                    :: /y: 覆盖现有文件不提示
                    :: >nul 2>&1: 不显示复制信息
                    copy /y "!filePath!" "!destPath!" >nul 2>&1
                    
                    :: 检查复制是否成功
                    if !errorlevel! equ 0 (
                        :: 复制成功,计数器加1
                        set /a filesCopied+=1
                        echo ✅ 已复制: !filePath!
                    ) else (
                        :: 复制失败
                        echo ❌ 复制失败: !filePath!
                    )
                ) else (
                    :: 源文件不存在
                    echo ⚠️ 源文件不存在: !filePath!
                )
            ) else (
                :: 文件在排除路径中,跳过
                echo ⚠️ 跳过(排除路径): !filePath!
            )
        )
    )
)

:: ==============================================
:: 清理和结果输出部分
:: ==============================================

:: 删除临时文件
del "%TEMP_FILE%" >nul 2>&1

echo =========================================
echo.

:: 根据复制结果输出相应信息
if %filesCopied% equ 0 (
    echo 📌 未找到或复制任何文件
) else (
    echo 🎉 共复制 %filesCopied% 个文件
)

:: 显示执行摘要
echo 📁 目标目录: %TARGET_DIR%
echo 🔍 排除路径: %excludePattern%

:: 暂停,等待用户按键继续
pause

:: ==============================================
:: 脚本说明:
:: 1. 本脚本用于在Windows环境下提取指定时间段内的Git修改文件
:: 2. 支持排除特定路径的文件
:: 3. 自动创建目标目录结构
:: 4. 只复制实际存在的文件
:: 5. 提供详细的执行过程反馈
:: ==============================================
相关推荐
小邓的技术笔记2 小时前
Git 中模糊搜索分支名称并创建本地跟踪分支
git
suijishengchengde2 小时前
****LINUX时间同步配置*****
linux·运维
qiuqyue3 小时前
基于虹软Linux Pro SDK的多路RTSP流并发接入、解码与帧级处理实践
linux·运维·网络
切糕师学AI3 小时前
Linux 操作系统简介
linux
南烟斋..3 小时前
GDB调试核心指南
linux·服务器
爱跑马的程序员3 小时前
Linux 如何查看文件夹的大小(du、df、ls、find)
linux·运维·ubuntu
Elastic 中国社区官方博客4 小时前
Elastic:DevRel 通讯 — 2026 年 1 月
大数据·数据库·人工智能·elasticsearch·搜索引擎·ai·全文检索
oMcLin6 小时前
如何在 Ubuntu 22.04 LTS 上部署并优化 Magento 电商平台,提升高并发请求的响应速度与稳定性?
linux·运维·ubuntu
Qinti_mm6 小时前
Linux io_uring:高性能异步I/O革命
linux·i/o·io_uring