#!/bin/bash

# pty_files_find.sh
# 다양한 조건으로 파일을 검색하는 스크립트
# 사용법:
#   ./pty_files_find.sh "*.log" -d 10         # 현재 디렉토리에서 .log 파일 중 10일 이상 지난 파일 검색
#   ./pty_files_find.sh "*.txt" -r -h 24      # 하위 디렉토리까지 .txt 파일 중 24시간 이상 지난 파일 검색
#   ./pty_files_find.sh "./*" -zerofiles      # 현재 디렉토리에서 0바이트 파일 검색
#   ./pty_files_find.sh "*.log" -r -zerofiles # 하위 디렉토리까지 .log 파일 중 0바이트 파일 검색

show_usage() {
    echo "사용법: $0 <검색패턴> [옵션]"
    echo ""
    echo "필수 인자:"
    echo "  검색패턴          검색할 파일 패턴 (예: *.log, *.txt, ./* 등)"
    echo "                    ./*  : 현재 디렉토리의 모든 파일"
    echo "                    *.log : 현재 디렉토리의 .log 파일"
    echo "                    /var/log/*.log : /var/log의 .log 파일"
    echo ""
    echo "검색 조건 옵션:"
    echo "  -d 일수           지정한 일수보다 오래된 파일 검색"
    echo "  -h 시간           지정한 시간보다 오래된 파일 검색"
    echo "  -zerofiles        0바이트 파일 검색"
    echo "  -emptydir         빈 디렉토리 검색"
    echo "  -size 크기        특정 크기의 파일 검색 (예: +10M, -1k, 100c)"
    echo "                    (+: 초과, -: 미만, 단위: c=byte, k=KB, M=MB, G=GB)"
    echo "  -user 사용자      특정 사용자 소유 파일 검색"
    echo "  -perm 권한        특정 권한의 파일 검색 (예: 777, 644)"
    echo ""
    echo "공통 옵션:"
    echo "  -r                하위 디렉토리까지 재귀적으로 검색"
    echo "  -t 타입           파일 타입 (f: 파일만, d: 디렉토리만, l: 심볼릭링크)"
    echo "  -s                파일 크기와 함께 표시"
    echo "  -l                상세 정보 표시 (ls -lh 형식)"
    echo "  -maxdepth N       검색 깊이 제한 (1: 현재 디렉토리만)"
    echo "  -count            개수만 표시"
    echo "  --delete          검색된 파일/디렉토리 삭제 (확인 후 실행)"
    echo "  --delete-force    검색된 파일/디렉토리 강제 삭제 (확인 없이 즉시 삭제)"
    echo ""
    echo "예제:"
    echo "  $0 '*.log' -d 10              # 현재 디렉토리의 .log 파일 중 10일 이상 지난 파일"
    echo "  $0 '*.log' -r -d 10           # 하위 디렉토리까지 .log 파일 중 10일 이상 지난 파일"
    echo "  $0 '*.txt' -h 24              # 현재 디렉토리의 .txt 파일 중 24시간 이상 지난 파일"
    echo "  $0 './*' -zerofiles           # 현재 디렉토리의 모든 0바이트 파일"
    echo "  $0 '*.log' -r -zerofiles      # 하위 디렉토리까지 .log 파일 중 0바이트 파일"
    echo "  $0 './*' -r -emptydir         # 하위 디렉토리까지 모든 빈 디렉토리"
    echo "  $0 '/var/log/*.log' -size +100M  # /var/log의 .log 파일 중 100MB 이상"
    echo "  $0 '*.tmp' -r -size -1k       # 하위 디렉토리까지 .tmp 파일 중 1KB 미만"
    echo "  $0 './*' -user root           # 현재 디렉토리의 root 소유 파일"
    echo "  $0 '*.sh' -perm 777           # 현재 디렉토리의 .sh 파일 중 777 권한"
    echo "  $0 '*.log' -r -d 30 -s        # 하위까지 .log 파일 중 30일 이상, 크기 표시"
    echo "  $0 './*' -maxdepth 2 -zerofiles  # 최대 2단계 깊이까지 0바이트 파일"
    echo "  $0 '*.log' -d 30 --delete     # 30일 이상 지난 .log 파일 삭제 (확인 후)"
    echo "  $0 '*.log' -d 30 --delete-force  # 30일 이상 지난 .log 파일 강제 삭제"
    exit 1
}

# 첫 번째 인자 확인 (검색 패턴)
if [ $# -eq 0 ]; then
    echo "오류: 검색 패턴을 지정해야 합니다."
    echo ""
    show_usage
fi

# 첫 번째 인자가 옵션인지 확인
if [[ "$1" == -* ]]; then
    echo "오류: 첫 번째 인자는 검색 패턴이어야 합니다."
    echo ""
    show_usage
fi

# 첫 번째 인자를 검색 패턴으로 설정
SEARCH_PATTERN="$1"
shift

# 패턴에서 경로와 파일명 분리
if [[ "$SEARCH_PATTERN" == */* ]]; then
    # 경로가 포함된 경우
    SEARCH_PATH="${SEARCH_PATTERN%/*}"
    FILE_PATTERN="${SEARCH_PATTERN##*/}"
    # 경로가 비어있으면 루트로 설정
    if [ -z "$SEARCH_PATH" ]; then
        SEARCH_PATH="/"
    fi
else
    # 경로가 없는 경우 현재 디렉토리
    SEARCH_PATH="."
    FILE_PATTERN="$SEARCH_PATTERN"
fi

# 기본값 설정
DAYS=""
HOURS=""
FILE_TYPE=""
SHOW_SIZE=false
SHOW_DETAIL=false
SHOW_COUNT=false
SEARCH_MODE=""
FILE_SIZE=""
FILE_USER=""
FILE_PERM=""
MAX_DEPTH="1"
RECURSIVE=false
DELETE_MODE=false
DELETE_FORCE=false

# 옵션 파싱
while [[ $# -gt 0 ]]; do
    case $1 in
        -d)
            DAYS="$2"
            SEARCH_MODE="old"
            shift 2
            ;;
        -h)
            HOURS="$2"
            SEARCH_MODE="old"
            shift 2
            ;;
        -zerofiles)
            SEARCH_MODE="zero"
            shift
            ;;
        -emptydir)
            SEARCH_MODE="emptydir"
            FILE_TYPE="d"
            shift
            ;;
        -size)
            FILE_SIZE="$2"
            SEARCH_MODE="size"
            shift 2
            ;;
        -user)
            FILE_USER="$2"
            SEARCH_MODE="user"
            shift 2
            ;;
        -perm)
            FILE_PERM="$2"
            SEARCH_MODE="perm"
            shift 2
            ;;
        -r)
            RECURSIVE=true
            MAX_DEPTH=""
            shift
            ;;
        -t)
            FILE_TYPE="$2"
            shift 2
            ;;
        -s)
            SHOW_SIZE=true
            shift
            ;;
        -l)
            SHOW_DETAIL=true
            shift
            ;;
        -maxdepth)
            MAX_DEPTH="$2"
            RECURSIVE=false
            shift 2
            ;;
        -count)
            SHOW_COUNT=true
            shift
            ;;
        --delete)
            DELETE_MODE=true
            shift
            ;;
        --delete-force)
            DELETE_MODE=true
            DELETE_FORCE=true
            shift
            ;;
        -help|--help)
            show_usage
            ;;
        *)
            echo "오류: 알 수 없는 옵션: $1"
            echo ""
            show_usage
            ;;
    esac
done

# 검색 모드가 지정되지 않은 경우 기본 검색 모드로 설정
if [ -z "$SEARCH_MODE" ]; then
    SEARCH_MODE="pattern"
fi

# 검색 경로 확인
if [ ! -d "$SEARCH_PATH" ]; then
    echo "오류: 검색 경로 '$SEARCH_PATH'가 존재하지 않습니다."
    exit 1
fi

# 숫자 유효성 검사
if [ -n "$DAYS" ]; then
    if ! [[ "$DAYS" =~ ^[0-9]+$ ]]; then
        echo "오류: 일수는 숫자여야 합니다."
        exit 1
    fi
fi

if [ -n "$HOURS" ]; then
    if ! [[ "$HOURS" =~ ^[0-9]+$ ]]; then
        echo "오류: 시간은 숫자여야 합니다."
        exit 1
    fi
fi

# find 명령어 옵션 구성
FIND_CMD="find \"$SEARCH_PATH\""

# 최대 깊이 설정 (-r 옵션이 없고 -maxdepth도 지정되지 않은 경우 기본값 1)
if [ -n "$MAX_DEPTH" ]; then
    FIND_CMD="$FIND_CMD -maxdepth $MAX_DEPTH"
fi

# 파일 패턴 적용
if [ "$FILE_PATTERN" != "*" ]; then
    FIND_CMD="$FIND_CMD -name \"$FILE_PATTERN\""
fi

# 파일 타입 옵션
if [ "$FILE_TYPE" = "f" ]; then
    FIND_CMD="$FIND_CMD -type f"
elif [ "$FILE_TYPE" = "d" ]; then
    FIND_CMD="$FIND_CMD -type d"
elif [ "$FILE_TYPE" = "l" ]; then
    FIND_CMD="$FIND_CMD -type l"
fi

# 검색 조건 설정
SEARCH_DESC=""
case $SEARCH_MODE in
    pattern)
        SEARCH_DESC="파일명 패턴 매칭"
        ;;
    old)
        if [ -n "$DAYS" ] && [ -n "$HOURS" ]; then
            echo "오류: -d와 -h 옵션은 동시에 사용할 수 없습니다."
            exit 1
        fi
        if [ -n "$DAYS" ]; then
            FIND_CMD="$FIND_CMD -mtime +$DAYS"
            SEARCH_DESC="${DAYS}일 이상 지난 파일"
        else
            MINUTES=$((HOURS * 60))
            FIND_CMD="$FIND_CMD -mmin +$MINUTES"
            SEARCH_DESC="${HOURS}시간 이상 지난 파일"
        fi
        ;;
    zero)
        FIND_CMD="$FIND_CMD -type f -size 0"
        SEARCH_DESC="0바이트 파일"
        ;;
    emptydir)
        FIND_CMD="$FIND_CMD -type d -empty"
        SEARCH_DESC="빈 디렉토리"
        ;;
    size)
        FIND_CMD="$FIND_CMD -size $FILE_SIZE"
        SEARCH_DESC="크기: $FILE_SIZE"
        ;;
    user)
        FIND_CMD="$FIND_CMD -user $FILE_USER"
        SEARCH_DESC="소유자: $FILE_USER"
        ;;
    perm)
        FIND_CMD="$FIND_CMD -perm $FILE_PERM"
        SEARCH_DESC="권한: $FILE_PERM"
        ;;
esac

# 헤더 출력
echo "============================================"
echo "파일 검색 결과"
echo "============================================"
echo "검색 패턴: $SEARCH_PATTERN"
echo "검색 경로: $SEARCH_PATH"
echo "검색 조건: $SEARCH_DESC"
if [ "$RECURSIVE" = true ]; then
    echo "재귀 검색: 예 (모든 하위 디렉토리)"
elif [ -n "$MAX_DEPTH" ]; then
    echo "검색 깊이: $MAX_DEPTH"
fi
if [ -n "$FILE_TYPE" ]; then
    case $FILE_TYPE in
        f) echo "파일 타입: 파일만" ;;
        d) echo "파일 타입: 디렉토리만" ;;
        l) echo "파일 타입: 심볼릭링크만" ;;
    esac
fi
echo "============================================"
echo ""

# 개수만 표시하는 경우
if [ "$SHOW_COUNT" = true ]; then
    COUNT=$(eval $FIND_CMD 2>/dev/null | wc -l)
    echo "총 ${COUNT}개의 항목을 찾았습니다."
    exit 0
fi

# 파일 찾기 및 결과 출력
if [ "$SHOW_DETAIL" = true ]; then
    # 상세 정보 표시
    eval $FIND_CMD -exec ls -lhd {} \; 2>/dev/null | sort -k9
    COUNT=$(eval $FIND_CMD 2>/dev/null | wc -l)
elif [ "$SHOW_SIZE" = true ]; then
    # 크기와 함께 표시
    eval $FIND_CMD -exec ls -lhd {} \; 2>/dev/null | awk '{print $5 "\t" $9}' | sort -k2
    COUNT=$(eval $FIND_CMD 2>/dev/null | wc -l)
else
    # 기본: 경로만 표시
    eval $FIND_CMD 2>/dev/null | sort
    COUNT=$(eval $FIND_CMD 2>/dev/null | wc -l)
fi

# 결과 요약
echo ""
echo "============================================"
echo "총 ${COUNT}개의 항목을 찾았습니다."
echo "============================================"

# 총 크기 계산 (파일인 경우만)
if [ "$SEARCH_MODE" != "emptydir" ] && ([ "$FILE_TYPE" = "f" ] || [ -z "$FILE_TYPE" ] || [ "$SEARCH_MODE" = "zero" ] || [ "$SEARCH_MODE" = "size" ]); then
    TOTAL_SIZE=$(eval $FIND_CMD -type f -exec du -cb {} + 2>/dev/null | tail -1 | cut -f1)
    if [ -n "$TOTAL_SIZE" ] && [ "$TOTAL_SIZE" != "0" ]; then
        # 바이트를 사람이 읽기 쉬운 형식으로 변환
        TOTAL_SIZE_HUMAN=$(numfmt --to=iec-i --suffix=B $TOTAL_SIZE 2>/dev/null || echo "${TOTAL_SIZE} bytes")
        echo "총 파일 크기: $TOTAL_SIZE_HUMAN"
        echo "============================================"
    fi
fi

# 삭제 모드 처리
if [ "$DELETE_MODE" = true ]; then
    if [ "$COUNT" -eq 0 ]; then
        echo ""
        echo "삭제할 항목이 없습니다."
        exit 0
    fi

    # 강제 삭제가 아닌 경우 확인 받기
    PROCEED_DELETE=false
    if [ "$DELETE_FORCE" = true ]; then
        PROCEED_DELETE=true
        echo ""
        echo "============================================"
        echo "강제 삭제 모드: ${COUNT}개 항목을 삭제합니다."
        echo "============================================"
    else
        echo ""
        echo "============================================"
        echo "경고: 위의 ${COUNT}개 항목을 삭제하시겠습니까?"
        echo "============================================"
        read -p "삭제하시겠습니까? (y/N): " -n 1 -r
        echo ""
        if [[ $REPLY =~ ^[Yy]$ ]]; then
            PROCEED_DELETE=true
        fi
    fi

    if [ "$PROCEED_DELETE" = true ]; then
        echo ""
        echo "삭제 중..."
        DELETED_COUNT=0
        FAILED_COUNT=0

        # 파일 목록을 배열로 저장
        mapfile -t FILES_TO_DELETE < <(eval $FIND_CMD 2>/dev/null)

        # 각 파일/디렉토리 삭제
        for item in "${FILES_TO_DELETE[@]}"; do
            if [ -d "$item" ]; then
                # 디렉토리인 경우
                if rmdir "$item" 2>/dev/null; then
                    echo "삭제됨: $item"
                    ((DELETED_COUNT++))
                else
                    echo "삭제 실패: $item (디렉토리가 비어있지 않거나 권한 부족)"
                    ((FAILED_COUNT++))
                fi
            else
                # 파일인 경우
                if rm -f "$item" 2>/dev/null; then
                    echo "삭제됨: $item"
                    ((DELETED_COUNT++))
                else
                    echo "삭제 실패: $item (권한 부족)"
                    ((FAILED_COUNT++))
                fi
            fi
        done

        echo ""
        echo "============================================"
        echo "삭제 완료: ${DELETED_COUNT}개 항목"
        if [ "$FAILED_COUNT" -gt 0 ]; then
            echo "삭제 실패: ${FAILED_COUNT}개 항목"
        fi
        echo "============================================"
    else
        echo ""
        echo "삭제가 취소되었습니다."
    fi
fi

exit 0
