#!/bin/bash # 压缩脚本 # 使用方法: # ./scripts/compress.sh # 使用默认配置(不包含 node_modules) # ./scripts/compress.sh --include-node-modules # 使用默认配置(包含 node_modules) # ./scripts/compress.sh -n # 使用默认配置(包含 node_modules,简写) # ./scripts/compress.sh --env production --version 1.0.0 # 指定环境和版本 # ./scripts/compress.sh --env test --version 1.0.0 -n # 组合使用多个参数 # ./scripts/compress.sh src/ package.json # 自定义文件/文件夹列表 set -e # 颜色输出 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # 默认值 ENV="" VERSION="" INCLUDE_NODE_MODULES=false # 解析命令行参数 CUSTOM_ITEMS=() while [[ $# -gt 0 ]]; do case $1 in --include-node-modules|-n) INCLUDE_NODE_MODULES=true shift ;; --env) if [ -z "$2" ]; then echo -e "${RED}错误: --env 参数需要一个值${NC}" exit 1 fi ENV="$2" shift 2 ;; --version) if [ -z "$2" ]; then echo -e "${RED}错误: --version 参数需要一个值${NC}" exit 1 fi VERSION="$2" shift 2 ;; *) CUSTOM_ITEMS+=("$1") shift ;; esac done # 构建输出文件名 OUTPUT_FILE="competition-management-service" if [ -n "$ENV" ]; then OUTPUT_FILE="${OUTPUT_FILE}-${ENV}" fi if [ -n "$VERSION" ]; then OUTPUT_FILE="${OUTPUT_FILE}-${VERSION}" fi OUTPUT_FILE="${OUTPUT_FILE}.tgz" # 默认要压缩的文件和文件夹(如果用户没有指定) DEFAULT_ITEMS=( "dist" "package.json" "tsconfig.json" "ecosystem.config.js" "prisma/" ".env" ".env.development" ".env.production" ".env.test" ) # 如果指定了包含 node_modules,则添加到默认列表的开头 if [ "$INCLUDE_NODE_MODULES" = true ]; then DEFAULT_ITEMS=("node_modules" "${DEFAULT_ITEMS[@]}") fi # 排除的文件和文件夹模式 EXCLUDE_PATTERNS=( "docs/" "scripts/" "sql/" ".git" ".DS_Store" "*.log" "./logs" "coverage" "*.tmp" "*.temp" ".cache" ".pnpm-store" ) # 获取脚本所在目录 SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" # 切换到项目根目录 cd "$PROJECT_ROOT" echo -e "${GREEN}📦 开始压缩项目...${NC}" if [ -n "$ENV" ]; then echo -e "${BLUE}环境: ${ENV}${NC}" fi if [ -n "$VERSION" ]; then echo -e "${BLUE}版本: ${VERSION}${NC}" fi echo "" # 确定要压缩的文件和文件夹 if [ ${#CUSTOM_ITEMS[@]} -eq 0 ]; then if [ "$INCLUDE_NODE_MODULES" = true ]; then echo -e "${YELLOW}未指定文件/文件夹,使用默认配置(包含 node_modules)${NC}" else echo -e "${YELLOW}未指定文件/文件夹,使用默认配置(不包含 node_modules)${NC}" fi ITEMS_TO_COMPRESS=("${DEFAULT_ITEMS[@]}") else echo -e "${YELLOW}使用自定义文件/文件夹列表${NC}" ITEMS_TO_COMPRESS=("${CUSTOM_ITEMS[@]}") fi # 验证文件和文件夹是否存在 echo -e "${BLUE}检查文件/文件夹是否存在...${NC}" MISSING_ITEMS=() for item in "${ITEMS_TO_COMPRESS[@]}"; do if [ ! -e "$item" ]; then MISSING_ITEMS+=("$item") echo -e "${RED} ⚠️ 警告: $item 不存在,将被跳过${NC}" else echo -e "${GREEN} ✅ $item${NC}" fi done # 如果有缺失的文件,询问是否继续 if [ ${#MISSING_ITEMS[@]} -gt 0 ]; then echo "" echo -e "${YELLOW}发现 ${#MISSING_ITEMS[@]} 个不存在的文件/文件夹${NC}" read -p "是否继续压缩? (y/n) " -n 1 -r echo "" if [[ ! $REPLY =~ ^[Yy]$ ]]; then echo -e "${RED}已取消压缩${NC}" exit 1 fi fi # 构建 tar 排除选项 EXCLUDE_ARGS=() for pattern in "${EXCLUDE_PATTERNS[@]}"; do EXCLUDE_ARGS+=(--exclude="$pattern") done # 如果输出文件已存在,询问是否覆盖 if [ -f "$OUTPUT_FILE" ]; then echo "" echo -e "${YELLOW}输出文件 $OUTPUT_FILE 已存在${NC}" read -p "是否覆盖? (y/n) " -n 1 -r echo "" if [[ ! $REPLY =~ ^[Yy]$ ]]; then echo -e "${RED}已取消压缩${NC}" exit 1 fi rm -f "$OUTPUT_FILE" fi # 执行压缩 echo "" echo -e "${BLUE}正在压缩...${NC}" # 使用 tar 压缩 tar -czf "$OUTPUT_FILE" \ "${EXCLUDE_ARGS[@]}" \ "${ITEMS_TO_COMPRESS[@]}" 2>/dev/null || { echo -e "${RED}压缩失败${NC}" exit 1 } # 检查压缩结果 if [ ! -f "$OUTPUT_FILE" ]; then echo -e "${RED}错误: 压缩文件未生成${NC}" exit 1 fi # 显示压缩文件信息 FILE_SIZE=$(du -h "$OUTPUT_FILE" | cut -f1) echo "" echo -e "${GREEN}═══════════════════════════════════════${NC}" echo -e "${GREEN}✅ 压缩完成!${NC}" echo -e "${GREEN}═══════════════════════════════════════${NC}" echo "" echo "📦 输出文件: $OUTPUT_FILE" echo "📊 文件大小: $FILE_SIZE" echo "📍 位置: $(pwd)/$OUTPUT_FILE" if [ -n "$ENV" ]; then echo "🌍 环境: $ENV" fi if [ -n "$VERSION" ]; then echo "🏷️ 版本: $VERSION" fi echo "" echo "📝 已压缩的内容:" for item in "${ITEMS_TO_COMPRESS[@]}"; do if [ -e "$item" ]; then echo " ✅ $item" fi done echo "" echo "🚫 已排除的内容:" for pattern in "${EXCLUDE_PATTERNS[@]}"; do echo " ❌ $pattern" done echo ""