|
|
#!/usr/bin/env bash
|
|
|
# clean_outputs.sh — 清理编译输出与日志垃圾文件
|
|
|
#
|
|
|
# 用法:
|
|
|
# clean_outputs.sh [选项]
|
|
|
#
|
|
|
# 选项:
|
|
|
# --logs 清理 output/logs/ 下的运行日志(保留 last_run.txt / last_failed.txt)
|
|
|
# --analyze 清理 output/analyze/ 下的单用例分析结果
|
|
|
# --build 清理 build_lab*/ 构建目录
|
|
|
# --test-result 清理 test/test_result/ 下的测试产物
|
|
|
# --all 清理以上全部
|
|
|
# --dry-run 只打印将要删除的内容,不实际删除
|
|
|
# --yes 跳过确认提示,直接删除(配合 --logs / --all 等使用)
|
|
|
#
|
|
|
# 不带任何选项时交互式选择。
|
|
|
|
|
|
set -euo pipefail
|
|
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
|
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
|
|
|
|
RED='\033[0;31m'
|
|
|
GREEN='\033[0;32m'
|
|
|
YELLOW='\033[1;33m'
|
|
|
CYAN='\033[0;36m'
|
|
|
NC='\033[0m'
|
|
|
|
|
|
DO_LOGS=false
|
|
|
DO_ANALYZE=false
|
|
|
DO_BUILD=false
|
|
|
DO_TEST_RESULT=false
|
|
|
DRY_RUN=false
|
|
|
AUTO_YES=false
|
|
|
|
|
|
if [[ $# -eq 0 ]]; then
|
|
|
# 交互模式
|
|
|
printf '%bclean_outputs.sh — interactive mode%b\n' "$CYAN" "$NC"
|
|
|
printf 'Select what to clean (space-separated numbers, e.g. "1 3"):\n'
|
|
|
printf ' 1) output/logs/ — run logs\n'
|
|
|
printf ' 2) output/analyze/ — single-case analysis results\n'
|
|
|
printf ' 3) build_lab*/ — CMake build directories\n'
|
|
|
printf ' 4) test/test_result/ — test artifacts\n'
|
|
|
printf ' 0) cancel\n'
|
|
|
read -r -p 'choice: ' choices
|
|
|
for c in $choices; do
|
|
|
case "$c" in
|
|
|
1) DO_LOGS=true ;;
|
|
|
2) DO_ANALYZE=true ;;
|
|
|
3) DO_BUILD=true ;;
|
|
|
4) DO_TEST_RESULT=true ;;
|
|
|
0) printf 'cancelled.\n'; exit 0 ;;
|
|
|
*) printf '%bunknown option: %s (ignored)%b\n' "$YELLOW" "$c" "$NC" ;;
|
|
|
esac
|
|
|
done
|
|
|
fi
|
|
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
|
case "$1" in
|
|
|
--logs) DO_LOGS=true ;;
|
|
|
--analyze) DO_ANALYZE=true ;;
|
|
|
--build) DO_BUILD=true ;;
|
|
|
--test-result) DO_TEST_RESULT=true ;;
|
|
|
--all) DO_LOGS=true; DO_ANALYZE=true; DO_BUILD=true; DO_TEST_RESULT=true ;;
|
|
|
--dry-run) DRY_RUN=true ;;
|
|
|
--yes|-y) AUTO_YES=true ;;
|
|
|
*)
|
|
|
printf '%bunknown option: %s%b\n' "$YELLOW" "$1" "$NC" >&2
|
|
|
;;
|
|
|
esac
|
|
|
shift
|
|
|
done
|
|
|
|
|
|
if [[ "$DO_LOGS" == false && "$DO_ANALYZE" == false && \
|
|
|
"$DO_BUILD" == false && "$DO_TEST_RESULT" == false ]]; then
|
|
|
printf 'nothing selected. use --help or run without arguments for interactive mode.\n' >&2
|
|
|
exit 0
|
|
|
fi
|
|
|
|
|
|
# ---------- 收集要删除的路径 ----------
|
|
|
|
|
|
declare -a TARGETS=()
|
|
|
|
|
|
if [[ "$DO_LOGS" == true ]]; then
|
|
|
LOG_ROOT="$REPO_ROOT/output/logs"
|
|
|
if [[ -d "$LOG_ROOT" ]]; then
|
|
|
# 删除所有子目录(即每次的 run dir),保留 last_run.txt / last_failed.txt
|
|
|
while IFS= read -r -d '' d; do
|
|
|
TARGETS+=("$d")
|
|
|
done < <(find "$LOG_ROOT" -mindepth 2 -maxdepth 2 -type d -print0 2>/dev/null)
|
|
|
fi
|
|
|
fi
|
|
|
|
|
|
if [[ "$DO_ANALYZE" == true ]]; then
|
|
|
ANALYZE_ROOT="$REPO_ROOT/output/analyze"
|
|
|
if [[ -d "$ANALYZE_ROOT" ]]; then
|
|
|
while IFS= read -r -d '' d; do
|
|
|
TARGETS+=("$d")
|
|
|
done < <(find "$ANALYZE_ROOT" -mindepth 1 -maxdepth 1 -print0 2>/dev/null)
|
|
|
fi
|
|
|
fi
|
|
|
|
|
|
if [[ "$DO_BUILD" == true ]]; then
|
|
|
while IFS= read -r -d '' d; do
|
|
|
TARGETS+=("$d")
|
|
|
done < <(find "$REPO_ROOT" -maxdepth 1 -type d -name 'build_lab*' -print0 2>/dev/null)
|
|
|
fi
|
|
|
|
|
|
if [[ "$DO_TEST_RESULT" == true ]]; then
|
|
|
TR_ROOT="$REPO_ROOT/test/test_result"
|
|
|
if [[ -d "$TR_ROOT" ]]; then
|
|
|
TARGETS+=("$TR_ROOT")
|
|
|
fi
|
|
|
fi
|
|
|
|
|
|
if [[ ${#TARGETS[@]} -eq 0 ]]; then
|
|
|
printf '%bNothing to clean — target directories are already empty or do not exist.%b\n' "$GREEN" "$NC"
|
|
|
exit 0
|
|
|
fi
|
|
|
|
|
|
# ---------- 打印列表 ----------
|
|
|
|
|
|
printf '\n%bThe following will be %s:%b\n' "$YELLOW" \
|
|
|
"$([[ "$DRY_RUN" == true ]] && echo "listed (dry-run)" || echo "DELETED")" "$NC"
|
|
|
TOTAL_SIZE=0
|
|
|
for t in "${TARGETS[@]}"; do
|
|
|
SIZE=$(du -sh "$t" 2>/dev/null | cut -f1 || echo "?")
|
|
|
printf ' [%s] %s\n' "$SIZE" "$t"
|
|
|
done
|
|
|
printf '\n'
|
|
|
|
|
|
if [[ "$DRY_RUN" == true ]]; then
|
|
|
printf '%bDry-run mode: nothing deleted.%b\n' "$CYAN" "$NC"
|
|
|
exit 0
|
|
|
fi
|
|
|
|
|
|
# ---------- 确认 ----------
|
|
|
|
|
|
if [[ "$AUTO_YES" == false ]]; then
|
|
|
read -r -p "Proceed with deletion? [y/N] " confirm
|
|
|
case "$confirm" in
|
|
|
[yY][eE][sS]|[yY]) ;;
|
|
|
*)
|
|
|
printf 'cancelled.\n'
|
|
|
exit 0
|
|
|
;;
|
|
|
esac
|
|
|
fi
|
|
|
|
|
|
# ---------- 删除 ----------
|
|
|
|
|
|
DELETED=0
|
|
|
ERRORS=0
|
|
|
for t in "${TARGETS[@]}"; do
|
|
|
if rm -rf "$t" 2>/dev/null; then
|
|
|
printf '%b deleted: %s%b\n' "$GREEN" "$t" "$NC"
|
|
|
DELETED=$((DELETED + 1))
|
|
|
else
|
|
|
printf '%b ERROR deleting: %s%b\n' "$RED" "$t" "$NC"
|
|
|
ERRORS=$((ERRORS + 1))
|
|
|
fi
|
|
|
done
|
|
|
|
|
|
printf '\n'
|
|
|
if [[ $ERRORS -eq 0 ]]; then
|
|
|
printf '%bDone. %d item(s) deleted.%b\n' "$GREEN" "$DELETED" "$NC"
|
|
|
else
|
|
|
printf '%bDone. %d deleted, %d errors.%b\n' "$YELLOW" "$DELETED" "$ERRORS" "$NC"
|
|
|
exit 1
|
|
|
fi
|