File size: 9,948 Bytes
519b145 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 |
#!/bin/bash
# Script tự động tổ chức các file markdown theo ngày tạo và category
# Chạy: bash backend/scripts/organize_markdowns.sh [--dry-run] [--backup]
set -e
# Parse arguments
DRY_RUN=false
BACKUP=false
for arg in "$@"; do
case $arg in
--dry-run)
DRY_RUN=true
shift
;;
--backup)
BACKUP=true
shift
;;
*)
;;
esac
done
PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
REPORTS_DIR="${PROJECT_ROOT}/tài nguyên/báo cáo"
DOCS_DIR="${PROJECT_ROOT}/backend/docs"
echo "📁 Tổ chức file markdown theo ngày và category..."
if [ "$DRY_RUN" = true ]; then
echo "🔍 DRY-RUN MODE: Chỉ preview, không di chuyển file"
fi
echo ""
# Hàm xác định ngày tạo file
get_file_creation_date() {
local file="$1"
local git_date=""
local birth_date=""
local mod_date=""
local meta_date=""
local final_date=""
# Git history
if command -v git &> /dev/null && [ -d "${PROJECT_ROOT}/.git" ]; then
git_date=$(cd "$PROJECT_ROOT" && git log --diff-filter=A --format="%ai" -- "$file" 2>/dev/null | tail -1 | cut -d' ' -f1)
if [ -z "$git_date" ] || [[ ! "$git_date" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
git_date=""
fi
fi
# File birth time
if [[ "$OSTYPE" == "darwin"* ]]; then
birth_date=$(stat -f "%SB" -t "%Y-%m-%d" "$file" 2>/dev/null || stat -f "%Sm" -t "%Y-%m-%d" -B "$file" 2>/dev/null || echo "")
if [ -z "$birth_date" ]; then
birth_date=$(stat -f "%Sm" -t "%Y-%m-%d" "$file" 2>/dev/null || echo "")
fi
else
birth_date=$(stat -c "%y" "$file" 2>/dev/null | cut -d' ' -f1 || echo "")
fi
# File modified time
if [[ "$OSTYPE" == "darwin"* ]]; then
mod_date=$(stat -f "%Sm" -t "%Y-%m-%d" "$file" 2>/dev/null || echo "")
else
mod_date=$(stat -c "%y" "$file" 2>/dev/null | cut -d' ' -f1 || echo "")
fi
# Metadata trong file
if [ -f "$file" ]; then
meta_date=$(grep -iE "(created|date|ngày):\s*[0-9]{4}-[0-9]{2}-[0-9]{2}" "$file" 2>/dev/null | head -1 | grep -oE "[0-9]{4}-[0-9]{2}-[0-9]{2}" | head -1 || echo "")
fi
# Sử dụng ngày đầu tiên tìm được
if [ -n "$git_date" ]; then
final_date="$git_date"
elif [ -n "$birth_date" ]; then
final_date="$birth_date"
elif [ -n "$mod_date" ]; then
final_date="$mod_date"
elif [ -n "$meta_date" ]; then
final_date="$meta_date"
else
final_date=$(date +"%Y-%m-%d")
fi
# Validate format
if [[ ! "$final_date" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
final_date=$(date +"%Y-%m-%d")
fi
echo "$final_date"
}
# Hàm detect category từ tên file và nội dung
detect_category() {
local file="$1"
local filename=$(basename "$file" | tr '[:upper:]' '[:lower:]')
local category=""
# Ưu tiên 1: Metadata trong file
if [ -f "$file" ]; then
meta_category=$(grep -iE "category:\s*[a-z]+" "$file" 2>/dev/null | head -1 | grep -oE "category:\s*([a-z_]+)" | cut -d: -f2 | tr -d ' ' || echo "")
if [ -n "$meta_category" ]; then
echo "$meta_category"
return
fi
fi
# Ưu tiên 2: Tên file
declare -A category_keywords
category_keywords["database"]="database|postgresql|mysql|mongodb|redis|db_|_db|sql"
category_keywords["backend"]="backend|api|server|django|flask|fastapi|be_|_be|endpoint"
category_keywords["frontend"]="frontend|ui|react|vue|angular|component|fe_|_fe|interface"
category_keywords["devops"]="devops|docker|kubernetes|ci/cd|deploy|jenkins|terraform"
category_keywords["ml"]="ml|ai|model|training|neural|tensorflow|pytorch|embedding"
category_keywords["plan"]="plan|roadmap|planning|strategy|milestone"
category_keywords["setup"]="setup|config|install|installation|guide|tutorial"
local max_matches=0
for cat in "${!category_keywords[@]}"; do
matches=$(echo "$filename" | grep -oiE "${category_keywords[$cat]}" | wc -l | tr -d ' ')
if [ "$matches" -gt "$max_matches" ]; then
max_matches=$matches
category="$cat"
fi
done
# Ưu tiên 3: Nội dung file (100 dòng đầu)
if [ -z "$category" ] && [ -f "$file" ]; then
local content=$(head -100 "$file" | tr '[:upper:]' '[:lower:]')
max_matches=0
for cat in "${!category_keywords[@]}"; do
matches=$(echo "$content" | grep -oiE "${category_keywords[$cat]}" | wc -l | tr -d ' ')
if [ "$matches" -gt "$max_matches" ]; then
max_matches=$matches
category="$cat"
fi
done
fi
# Fallback
if [ -z "$category" ]; then
category="general"
fi
echo "$category"
}
# Hàm tạo folder và README nếu chưa có
ensure_category_folder() {
local date_folder="$1"
local category="$2"
local category_folder="${date_folder}/${category}"
if [ ! -d "$category_folder" ]; then
if [ "$DRY_RUN" = false ]; then
mkdir -p "$category_folder"
echo "✅ Đã tạo folder: $category_folder"
# Tạo README.md trong folder category
cat > "${category_folder}/README.md" << EOF
# Tài liệu ${category} - $(basename "$date_folder")
Folder này chứa các file markdown về **${category}** được tạo trong ngày $(basename "$date_folder").
## Danh sách file
$(find "$category_folder" -maxdepth 1 -name "*.md" ! -name README.md -type f | sed 's|.*/||' | sort | sed 's/^/- /')
## Category
${category}
## Ngày tạo
$(basename "$date_folder")
EOF
else
echo "🔍 [DRY-RUN] Sẽ tạo folder: $category_folder"
fi
fi
}
# Hàm di chuyển file markdown
move_markdown() {
local source_file="$1"
local target_dir="$2"
local filename=$(basename "$source_file")
local target_file="${target_dir}/${filename}"
if [ -f "$target_file" ]; then
if cmp -s "$source_file" "$target_file" 2>/dev/null; then
echo "⚠️ File trùng nội dung: $target_file (xóa file gốc)"
if [ "$DRY_RUN" = false ]; then
rm "$source_file"
fi
return 1
else
echo "⚠️ File đã tồn tại nhưng khác nội dung: $target_file"
return 1
fi
fi
if [ "$BACKUP" = true ] && [ "$DRY_RUN" = false ]; then
backup_dir="${PROJECT_ROOT}/.backup/markdowns/$(date +%Y%m%d_%H%M%S)"
mkdir -p "$backup_dir"
cp "$source_file" "${backup_dir}/${filename}"
fi
if [ "$DRY_RUN" = false ]; then
mv "$source_file" "$target_file"
echo "✅ Đã di chuyển: $filename → $target_dir"
else
echo "🔍 [DRY-RUN] Sẽ di chuyển: $filename → $target_dir"
fi
return 0
}
# Xử lý các file trong backend/docs
if [ -d "$DOCS_DIR" ]; then
echo "🔍 Tìm file markdown trong: $DOCS_DIR"
find "$DOCS_DIR" -maxdepth 1 -name "*.md" -type f | while read -r file; do
if [ -f "$file" ]; then
filename=$(basename "$file")
echo ""
echo "📄 Xử lý: $filename"
# Xác định ngày tạo
date_created=$(get_file_creation_date "$file")
echo " 📅 Ngày: $date_created"
# Detect category
category=$(detect_category "$file")
echo " 📂 Category: $category"
date_folder="${REPORTS_DIR}/${date_created}"
ensure_category_folder "$date_folder" "$category"
# Di chuyển file
move_markdown "$file" "${date_folder}/${category}"
fi
done
fi
# Tìm các file markdown lộn xộn khác
echo ""
echo "🔍 Tìm file markdown lộn xộn khác..."
EXCLUDE_DIRS=(
"node_modules"
"ops"
"chatbot/training"
".git"
".venv"
"__pycache__"
".cursor"
"tài nguyên/báo cáo"
".backup"
)
find "$PROJECT_ROOT" -name "*.md" -type f | while read -r file; do
skip=false
for exclude in "${EXCLUDE_DIRS[@]}"; do
if [[ "$file" == *"$exclude"* ]]; then
skip=true
break
fi
done
if [[ "$file" == *"tài nguyên/báo cáo"* ]]; then
skip=true
fi
if [ "$skip" = true ]; then
continue
fi
filename=$(basename "$file")
echo ""
echo "📄 Xử lý: $filename"
# Xác định ngày tạo
date_created=$(get_file_creation_date "$file")
echo " 📅 Ngày: $date_created"
# Detect category
category=$(detect_category "$file")
echo " 📂 Category: $category"
date_folder="${REPORTS_DIR}/${date_created}"
ensure_category_folder "$date_folder" "$category"
# Di chuyển file
move_markdown "$file" "${date_folder}/${category}"
done
echo ""
echo "✅ Hoàn tất tổ chức file markdown!"
echo ""
echo "📊 Thống kê:"
for date_folder in "${REPORTS_DIR}"/20*; do
if [ -d "$date_folder" ]; then
date_name=$(basename "$date_folder")
echo " 📁 $date_name:"
for category_folder in "${date_folder}"/*; do
if [ -d "$category_folder" ]; then
category_name=$(basename "$category_folder")
count=$(find "$category_folder" -maxdepth 1 -name "*.md" ! -name README.md -type f | wc -l | tr -d ' ')
if [ "$count" -gt 0 ]; then
echo " └─ $category_name: $count file(s)"
fi
fi
done
fi
done
if [ "$DRY_RUN" = true ]; then
echo ""
echo "💡 Chạy lại không có --dry-run để thực sự di chuyển file"
fi
|