174 lines
4.9 KiB
Bash
Executable File
174 lines
4.9 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# 文件版本管理 SOP 腳本
|
|
# 用途: 安全處理文件更新時的舊版本歸檔
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}"))" && pwd)
|
|
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
|
|
ARCHIVE_DIR="$PROJECT_ROOT/archive"
|
|
LOG_FILE="$PROJECT_ROOT/logs/file_migration.log"
|
|
|
|
# 顏色定義
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
RED='\033[0;31m'
|
|
NC='\033[0m'
|
|
|
|
# 確保必要目錄存在
|
|
setup_directories() {
|
|
mkdir -p "$PROJECT_ROOT/logs"
|
|
mkdir -p "$ARCHIVE_DIR"
|
|
|
|
if [[ ! -f "$LOG_FILE" ]]; then
|
|
echo "# 文件遷移日誌" > "$LOG_FILE"
|
|
echo "# 格式: [日期時間] 操作類型 | 原文件 -> 目標位置 | 操作者 | 原因" >> "$LOG_FILE"
|
|
echo "" >> "$LOG_FILE"
|
|
fi
|
|
}
|
|
|
|
# 記錄遷移日誌
|
|
log_migration() {
|
|
local operation="$1"
|
|
local source_file="$2"
|
|
local target_file="$3"
|
|
local reason="$4"
|
|
local operator="${5:-Claude Code}"
|
|
|
|
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
|
|
local log_entry="[$timestamp] $operation | $source_file -> $target_file | $operator | $reason"
|
|
|
|
echo "$log_entry" >> "$LOG_FILE"
|
|
echo -e "${GREEN}📋 記錄遷移: ${NC}$log_entry"
|
|
}
|
|
|
|
# 歸檔舊文件
|
|
archive_file() {
|
|
local source_file="$1"
|
|
local reason="$2"
|
|
local operator="${3:-Claude Code}"
|
|
|
|
if [[ ! -f "$source_file" ]]; then
|
|
echo -e "${RED}❌ 文件不存在: $source_file${NC}"
|
|
return 1
|
|
fi
|
|
|
|
# 生成歸檔目錄 (按日期)
|
|
local date_dir=$(date '+%Y-%m-%d')
|
|
local archive_date_dir="$ARCHIVE_DIR/$date_dir"
|
|
mkdir -p "$archive_date_dir"
|
|
|
|
# 生成新文件名 (加上時間前綴)
|
|
local filename=$(basename "$source_file")
|
|
local timestamp=$(date '+%H%M%S')
|
|
local archived_filename="${timestamp}_${filename}"
|
|
local target_file="$archive_date_dir/$archived_filename"
|
|
|
|
# 移動文件
|
|
mv "$source_file" "$target_file"
|
|
|
|
if [[ $? -eq 0 ]]; then
|
|
echo -e "${BLUE}📦 歸檔成功: ${NC}$source_file -> $target_file"
|
|
log_migration "ARCHIVE" "$source_file" "$target_file" "$reason" "$operator"
|
|
return 0
|
|
else
|
|
echo -e "${RED}❌ 歸檔失敗: $source_file${NC}"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# 安全替換文件 (先歸檔舊版本)
|
|
safe_replace() {
|
|
local old_file="$1"
|
|
local new_file="$2"
|
|
local reason="$3"
|
|
local operator="${4:-Claude Code}"
|
|
|
|
if [[ ! -f "$new_file" ]]; then
|
|
echo -e "${RED}❌ 新文件不存在: $new_file${NC}"
|
|
return 1
|
|
fi
|
|
|
|
if [[ -f "$old_file" ]]; then
|
|
# 先歸檔舊文件
|
|
archive_file "$old_file" "$reason" "$operator"
|
|
if [[ $? -ne 0 ]]; then
|
|
echo -e "${RED}❌ 無法歸檔舊文件,中止替換${NC}"
|
|
return 1
|
|
fi
|
|
fi
|
|
|
|
# 移動新文件到目標位置
|
|
mv "$new_file" "$old_file"
|
|
|
|
if [[ $? -eq 0 ]]; then
|
|
echo -e "${GREEN}✅ 安全替換完成: ${NC}$old_file"
|
|
log_migration "REPLACE" "$new_file" "$old_file" "$reason" "$operator"
|
|
return 0
|
|
else
|
|
echo -e "${RED}❌ 替換失敗${NC}"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# 查看遷移日誌
|
|
view_log() {
|
|
if [[ -f "$LOG_FILE" ]]; then
|
|
echo -e "${BLUE}📋 文件遷移日誌:${NC}"
|
|
cat "$LOG_FILE"
|
|
else
|
|
echo -e "${YELLOW}⚠️ 尚無遷移日誌${NC}"
|
|
fi
|
|
}
|
|
|
|
# 列出歸檔文件
|
|
list_archives() {
|
|
if [[ -d "$ARCHIVE_DIR" ]]; then
|
|
echo -e "${BLUE}📦 歸檔文件列表:${NC}"
|
|
find "$ARCHIVE_DIR" -type f -exec ls -la {} \; | sort
|
|
else
|
|
echo -e "${YELLOW}⚠️ 尚無歸檔文件${NC}"
|
|
fi
|
|
}
|
|
|
|
# 主函數
|
|
main() {
|
|
setup_directories
|
|
|
|
case "$1" in
|
|
"archive")
|
|
if [[ $# -lt 3 ]]; then
|
|
echo -e "${RED}使用方法: $0 archive 文件路徑 原因 [操作者]${NC}"
|
|
exit 1
|
|
fi
|
|
archive_file "$2" "$3" "$4"
|
|
;;
|
|
"replace")
|
|
if [[ $# -lt 4 ]]; then
|
|
echo -e "${RED}使用方法: $0 replace 舊文件 新文件 原因 [操作者]${NC}"
|
|
exit 1
|
|
fi
|
|
safe_replace "$2" "$3" "$4" "$5"
|
|
;;
|
|
"log")
|
|
view_log
|
|
;;
|
|
"list")
|
|
list_archives
|
|
;;
|
|
*)
|
|
echo -e "${BLUE}🗃️ 文件版本管理工具${NC}"
|
|
echo "用法:"
|
|
echo " $0 archive 文件路徑 原因 [操作者] # 歸檔文件"
|
|
echo " $0 replace 舊文件 新文件 原因 [操作者] # 安全替換文件"
|
|
echo " $0 log # 查看遷移日誌"
|
|
echo " $0 list # 列出歸檔文件"
|
|
echo ""
|
|
echo "範例:"
|
|
echo " $0 archive TASK_MANAGEMENT_OLD.md \"系統重構\" \"Claude Code\""
|
|
echo " $0 replace old.md new.md \"功能更新\" \"開發者\""
|
|
;;
|
|
esac
|
|
}
|
|
|
|
main "$@" |