compare_manuals.sh 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. #!/bin/bash
  2. # Script to compare manual files across different languages
  3. # Usage: ./compare_manuals.sh
  4. set -euo pipefail
  5. # Global variables for tracking issues and options
  6. HAS_ISSUES=0
  7. REMOVE_MODE=false
  8. # Colors for output
  9. RED='\033[0;31m'
  10. GREEN='\033[0;32m'
  11. YELLOW='\033[1;33m'
  12. BLUE='\033[0;34m'
  13. NC='\033[0m' # No Color
  14. # Base directory for manuals
  15. MANUAL_DIR="manual"
  16. ENGLISH_DIR="${MANUAL_DIR}/english"
  17. # Function to print colored output
  18. print_colored() {
  19. local color=$1
  20. local message=$2
  21. echo -e "${color}${message}${NC}"
  22. }
  23. # Function to get all language directories
  24. get_language_dirs() {
  25. find "${MANUAL_DIR}" -mindepth 1 -maxdepth 1 -type d | grep -v "${ENGLISH_DIR}" | sort
  26. }
  27. # Function to get all .md files and directories relative to base path
  28. get_structure() {
  29. local base_dir=$1
  30. if [[ ! -d "$base_dir" ]]; then
  31. return 1
  32. fi
  33. # Get all .md files and directories
  34. find "$base_dir" -name "*.md" -o -type d | \
  35. sed "s|^${base_dir}/||" | \
  36. grep -v "^$" | \
  37. sort
  38. }
  39. # Function to compare file content line by line
  40. compare_files() {
  41. local file1=$1
  42. local file2=$2
  43. if [[ ! -f "$file1" ]] || [[ ! -f "$file2" ]]; then
  44. return 1
  45. fi
  46. local f1_lines f2_lines
  47. f1_lines=$(wc -l < "$file1")
  48. f2_lines=$(wc -l < "$file2")
  49. # Compare files line by line
  50. if [[ $f1_lines -ne $f2_lines ]]; then
  51. echo "$f1_lines:$f2_lines"
  52. return 1
  53. fi
  54. return 0
  55. }
  56. # Function to check if path exists in language directory
  57. path_exists() {
  58. local lang_dir=$1
  59. local relative_path=$2
  60. local full_path="${lang_dir}/${relative_path}"
  61. [[ -e "$full_path" ]]
  62. }
  63. # Main comparison function
  64. compare_with_languages() {
  65. local english_dir=$1
  66. if [[ ! -d "$english_dir" ]]; then
  67. print_colored "$RED" "Error: English directory '$english_dir' not found!"
  68. exit 1
  69. fi
  70. print_colored "$BLUE" "=== Manual Structure Comparison ==="
  71. print_colored "$BLUE" "Base directory: $english_dir"
  72. if [[ "$REMOVE_MODE" == "true" ]]; then
  73. print_colored "$YELLOW" "REMOVE MODE: Files with mismatched line counts will be automatically removed"
  74. fi
  75. echo
  76. # Get English structure
  77. local english_structure
  78. english_structure=$(get_structure "$english_dir")
  79. if [[ -z "$english_structure" ]]; then
  80. print_colored "$YELLOW" "Warning: No .md files or directories found in $english_dir"
  81. return
  82. fi
  83. # Get all language directories
  84. local lang_dirs
  85. lang_dirs=$(get_language_dirs)
  86. if [[ -z "$lang_dirs" ]]; then
  87. print_colored "$YELLOW" "Warning: No other language directories found in $MANUAL_DIR"
  88. return
  89. fi
  90. print_colored "$GREEN" "Found language directories:"
  91. echo "$lang_dirs" | while read -r lang_dir; do
  92. echo " - $(basename "$lang_dir")"
  93. done
  94. echo
  95. # Compare each language with English
  96. while IFS= read -r lang_dir; do
  97. local lang_name
  98. lang_name=$(basename "$lang_dir")
  99. print_colored "$BLUE" "--- Comparing with $lang_name ---"
  100. local missing_files=()
  101. local different_files=()
  102. local missing_dirs=()
  103. local removed_files=()
  104. # Check each item in English structure
  105. while IFS= read -r item; do
  106. local english_path="${english_dir}/${item}"
  107. local lang_path="${lang_dir}/${item}"
  108. if [[ ! -e "$lang_path" ]]; then
  109. if [[ -d "$english_path" ]]; then
  110. missing_dirs+=("$item")
  111. HAS_ISSUES=1
  112. elif [[ -f "$english_path" ]]; then
  113. missing_files+=("$item")
  114. HAS_ISSUES=1
  115. fi
  116. elif [[ -f "$english_path" ]] && [[ -f "$lang_path" ]]; then
  117. # Both are files, compare content
  118. local diff_result
  119. set +e # Temporarily disable exit on error
  120. diff_result=$(compare_files "$english_path" "$lang_path")
  121. local compare_exit_code=$?
  122. set -e # Re-enable exit on error
  123. if [[ $compare_exit_code -ne 0 ]]; then
  124. HAS_ISSUES=1
  125. if [[ "$REMOVE_MODE" == "true" ]]; then
  126. # Remove the file with mismatched line count
  127. rm -f "$lang_path"
  128. removed_files+=("$item")
  129. print_colored "$RED" "REMOVED: $lang_path (line count mismatch)"
  130. else
  131. if [[ -n "$diff_result" ]]; then
  132. different_files+=("$item|$diff_result")
  133. else
  134. different_files+=("$item")
  135. fi
  136. fi
  137. fi
  138. fi
  139. done <<< "$english_structure"
  140. # Report results
  141. if [[ ${#missing_dirs[@]} -gt 0 ]]; then
  142. print_colored "$RED" "Missing directories in $lang_name:"
  143. printf ' %s\n' "${missing_dirs[@]}"
  144. echo
  145. fi
  146. if [[ ${#missing_files[@]} -gt 0 ]]; then
  147. print_colored "$RED" "Missing files in $lang_name:"
  148. printf ' %s\n' "${missing_files[@]}"
  149. echo
  150. fi
  151. if [[ ${#removed_files[@]} -gt 0 ]]; then
  152. print_colored "$RED" "Removed files with mismatched line counts in $lang_name:"
  153. printf ' %s\n' "${removed_files[@]}"
  154. echo
  155. fi
  156. if [[ ${#different_files[@]} -gt 0 ]]; then
  157. print_colored "$YELLOW" "Files with different content in $lang_name:"
  158. for file_info in "${different_files[@]}"; do
  159. if [[ "$file_info" == *"|"* ]]; then
  160. local file="${file_info%|*}"
  161. local line_counts="${file_info#*|}"
  162. local eng_lines="${line_counts%:*}"
  163. local lang_lines="${line_counts#*:}"
  164. printf ' %s (English: %d lines, %s: %d lines)\n' "$file" "$eng_lines" "$lang_name" "$lang_lines"
  165. else
  166. printf ' %s\n' "$file_info"
  167. fi
  168. done
  169. echo
  170. fi
  171. if [[ ${#missing_dirs[@]} -eq 0 ]] && [[ ${#missing_files[@]} -eq 0 ]] && [[ ${#different_files[@]} -eq 0 ]] && [[ ${#removed_files[@]} -eq 0 ]]; then
  172. print_colored "$GREEN" "✓ $lang_name structure and content matches English perfectly!"
  173. echo
  174. fi
  175. done <<< "$lang_dirs"
  176. }
  177. # Function to show detailed diff for specific files
  178. show_detailed_diff() {
  179. local english_dir=$1
  180. local lang_dir=$2
  181. local file_path=$3
  182. local english_file="${english_dir}/${file_path}"
  183. local lang_file="${lang_dir}/${file_path}"
  184. if [[ -f "$english_file" ]] && [[ -f "$lang_file" ]]; then
  185. print_colored "$BLUE" "--- Detailed diff for $file_path ---"
  186. print_colored "$BLUE" "English: $english_file"
  187. print_colored "$BLUE" "$(basename "$lang_dir"): $lang_file"
  188. echo
  189. # Show side-by-side diff with line numbers
  190. diff -u "$english_file" "$lang_file" || true
  191. echo
  192. fi
  193. }
  194. # Function to show summary statistics
  195. show_summary() {
  196. local english_dir=$1
  197. print_colored "$BLUE" "=== Summary Statistics ==="
  198. # Count English files and directories
  199. local english_files
  200. local english_dirs
  201. english_files=$(find "$english_dir" -name "*.md" | wc -l | tr -d ' ')
  202. english_dirs=$(find "$english_dir" -type d | wc -l | tr -d ' ')
  203. echo "English structure:"
  204. echo " - Directories: $english_dirs"
  205. echo " - .md files: $english_files"
  206. echo
  207. # Count for each language
  208. get_language_dirs | while read -r lang_dir; do
  209. local lang_name
  210. lang_name=$(basename "$lang_dir")
  211. local lang_files
  212. local lang_dirs_count
  213. lang_files=$(find "$lang_dir" -name "*.md" 2>/dev/null | wc -l | tr -d ' ')
  214. lang_dirs_count=$(find "$lang_dir" -type d 2>/dev/null | wc -l | tr -d ' ')
  215. echo "$lang_name structure:"
  216. echo " - Directories: $lang_dirs_count"
  217. echo " - .md files: $lang_files"
  218. echo
  219. done
  220. }
  221. # Main execution
  222. main() {
  223. # Check if manual directory exists
  224. if [[ ! -d "$MANUAL_DIR" ]]; then
  225. print_colored "$RED" "Error: Manual directory '$MANUAL_DIR' not found in current directory!"
  226. print_colored "$YELLOW" "Current directory: $(pwd)"
  227. exit 1
  228. fi
  229. # Check if English directory exists
  230. if [[ ! -d "$ENGLISH_DIR" ]]; then
  231. print_colored "$RED" "Error: English directory '$ENGLISH_DIR' not found!"
  232. exit 1
  233. fi
  234. print_colored "$GREEN" "Starting manual comparison..."
  235. echo "Current directory: $(pwd)"
  236. echo
  237. # Show summary first
  238. show_summary "$ENGLISH_DIR"
  239. # Compare structures and content
  240. # Compare structures and content
  241. compare_with_languages "$ENGLISH_DIR"
  242. if [[ $HAS_ISSUES -eq 0 ]]; then
  243. print_colored "$GREEN" "Comparison completed! All translations are perfect."
  244. exit 0
  245. else
  246. print_colored "$RED" "Comparison completed with issues found."
  247. exit 1
  248. fi
  249. }
  250. # Handle command line arguments
  251. # Handle command line arguments
  252. case "${1:-}" in
  253. -h|--help)
  254. echo "Usage: $0 [OPTIONS]"
  255. echo ""
  256. echo "Compare manual files across different languages"
  257. echo ""
  258. echo "OPTIONS:"
  259. echo " -h, --help Show this help message"
  260. echo " -s, --summary Show only summary statistics"
  261. echo " --remove Automatically remove files with mismatched line counts"
  262. echo ""
  263. echo "EXIT CODES:"
  264. echo " 0 All translations perfect (no missing files or line count mismatches)"
  265. echo " 1 Issues found (missing translations or line count mismatches)"
  266. echo ""
  267. echo "This script compares the structure and content of .md files"
  268. echo "in manual/english/ with all other language directories."
  269. echo "With --remove flag, files with different line counts are automatically deleted."
  270. exit 0
  271. ;;
  272. -s|--summary)
  273. show_summary "$ENGLISH_DIR"
  274. exit 0
  275. ;;
  276. --remove)
  277. REMOVE_MODE=true
  278. main
  279. ;;
  280. "")
  281. main
  282. ;;
  283. *)
  284. print_colored "$RED" "Unknown option: $1"
  285. print_colored "$YELLOW" "Use -h or --help for usage information"
  286. exit 1
  287. ;;
  288. esac