불필요한 Asset file 제거 Script (모듈 분리)
check_unused_assets:
@zsh script/check_unused_assets.sh
#!/bin/zsh
# ===============================
# 1. 유틸리티 함수 선언
# ===============================
to_camel_case() {
echo "$1" | awk -F'[-_ ]' '{
for(i=1;i<=NF;i++){
if(i==1) printf "%s", tolower($i);
else printf "%s%s", toupper(substr($i,1,1)), tolower(substr($i,2));
}
}'
}
print_table_header() {
echo "+--------------------------+-------+---------------------+"
echo "| VARIABLE | TYPE | ASSET FILE PATH |"
echo "+--------------------------+-------+---------------------+"
}
# ===============================
# 2. 설정값
# ===============================
search_dirs=("features" "lib")
image_extensions=("png" "jpg" "jpeg" "gif" "bmp" "svg" "webp")
RED=$'\033[31m'
BLUE=$'\033[34m'
RESET=$'\033[0m'
base_dir="assets/images"
image_dirs=()
# ===============================
# 3. 이미지 폴더 목록 동적 설정
# ===============================
if [[ ! -d "$base_dir" ]]; then
echo "기본 이미지 폴더 ($base_dir) 가 존재하지 않습니다."
exit 1
fi
# 안전하게 배열에 할당 (공백, 한글, 특수문자 폴더명도 OK)
all_dirs=()
while IFS= read -r dir; do
all_dirs+=("$dir")
done < <(find "$base_dir" -mindepth 1 -maxdepth 1 -type d | sort)
echo
echo "=== 이미지 폴더 검사 선택 ==="
echo
echo "a) 전체 폴더 검사 (all)"
echo "s) 특정 폴더 선택 검사(selective)"
echo "[폴더 검사할 범위를 정하기 위해 a 또는 s 중에서 선택]: "
read choice
if [[ "$choice" == "a" ]]; then
image_dirs=("${all_dirs[@]}")
elif [[ "$choice" == "s" ]]; then
# 폴더 목록 다시 출력
echo
echo "선택 가능한 폴더 목록:"
for ((i=1; i<=${#all_dirs[@]}; i++)); do
folder_name=$(basename "${all_dirs[$((i))]}")
echo " $i) $folder_name"
done
echo
echo "검사할 폴더 번호를 쉼표(,)로 구분하여 입력하세요 (예: 1,3):"
echo -n "번호 입력: "
read input_nums
# shellcheck disable=SC2296
nums=("${(@s/,/)input_nums}")
for num in "${nums[@]}"; do
if [[ "$num" =~ '^[0-9]+$' ]] && (( num >= 0 )) && (( num <= ${#all_dirs[@]} )); then
image_dirs+=("${all_dirs[$((num))]}")
else
echo "경고: 유효하지 않은 번호 무시됨: $num"
fi
done
if (( ${#image_dirs[@]} == 0 )); then
echo "선택된 폴더가 없습니다. 종료합니다."
exit 1
fi
else
echo "잘못된 선택입니다. 종료합니다."
exit 1
fi
# ===============================
# 4. 참조되지 않은 asset 찾기 (hashmap 방식)
# ===============================
any_asset_found=0
tmpfile=$(mktemp)
echo
echo "=== 스크립트 시작 ==="
echo "대상 이미지 폴더 목록: ${image_dirs[*]}"
echo "확장자 목록: ${image_extensions[*]}"
echo "검색 대상 폴더: ${search_dirs[*]}"
echo
print_table_header
# 1. 전체 소스에서 asset 변수명 패턴을 모두 grep해서 해시맵에 저장 (소문자 변환)
all_refs=()
for dir in "${search_dirs[@]}"; do
if [[ -d "$dir" ]]; then
all_refs+=($(grep -rhoE 'Assets\.images\.[a-zA-Z0-9_]+\.[a-zA-Z0-9_]+' "$dir" --include="*.dart"))
fi
done
typeset -A ref_map
for ref in "${all_refs[@]}"; do
ref_map["${ref:l}"]=1 # 소문자 변환
done
for dir in "${image_dirs[@]}"; do
echo "${BLUE}>> 폴더 확인: $dir${RESET}"
if [[ ! -d "$dir" ]]; then
echo " 폴더가 존재하지 않아 건너뜁니다."
continue
fi
find "$dir" -type f | while read -r filepath; do
filename=$(basename "$filepath")
ext="${filename##*.}"
lower_ext=$(echo "$ext" | tr '[:upper:]' '[:lower:]')
match=0
for valid_ext in "${image_extensions[@]}"; do
if [[ "$lower_ext" == "$valid_ext" ]]; then
match=1
break
fi
done
(( match == 0 )) && continue
any_asset_found=1
name_wo_ext="${filename%.*}"
parent_folder=$(basename "$(dirname "$filepath")")
camel_case_name=$(to_camel_case "$name_wo_ext")
var_name="Assets.images.${parent_folder}.${camel_case_name}"
var_name_lc="${var_name:l}"
# 해시맵에서 소문자 비교로 빠르게 체크
if [[ -z ${ref_map["$var_name_lc"]} ]]; then
echo "$filepath" >> "$tmpfile"
printf "| ${RED}%-24s${RESET} | %-5s | %-19s |\n" "$var_name" "$ext" "$filepath"
fi
done
done
echo "+--------------------------+-------+---------------------+"
unref_count=$(grep -cve '^\s*$' "$tmpfile")
if (( any_asset_found == 0 )); then
echo
echo "※ 검색된 asset 파일이 없습니다."
elif (( unref_count > 0 )); then
echo
echo "⚠️ 참조되지 않은 파일이 총 ${unref_count}개 있습니다."
echo -n "이 파일들을 모두 삭제하시겠습니까? [y/N]: "
read confirm
if [[ "$confirm" == [yY] ]]; then
echo "🗑️ 삭제를 시작합니다..."
deleted_count=0
while IFS= read -r file; do
if [[ -f "$file" ]]; then
rm -v -- "$file" && ((deleted_count++))
fi
done < "$tmpfile"
echo "✅ ${deleted_count}/${unref_count} 개 파일이 삭제되었습니다."
else
echo "❌ 삭제하지 않고 종료합니다."
fi
else
echo
echo "모든 asset이 참조되고 있습니다."
fi
rm -f "$tmpfile"
echo "=== 스크립트 종료 ==="
Last updated