finder.sh

This commit is contained in:
jads
2026-05-12 18:24:43 +03:00
parent c7edca3c3e
commit 870548020d
2 changed files with 265 additions and 0 deletions

View File

@@ -6,3 +6,14 @@
# combine.sh
Объединяет содержимое текстовых файлов из указанной директории в один файл. Удобно для подготовки контекста для AI, анализа кода или создания резюме проекта.
# finder.sh
Утилита командной строки для анализа файлов в директории: сбор статистики по расширениям или отображение списка файлов с возможностью фильтрации и исключений
## Возможности
- Подсчёт количества файлов по расширениям с сортировкой
- Фильтр по целевому расширению
- Показ путей к файлам (режим `-p`)
- Исключение директорий и отдельных расширений
- Рекурсивный и нерекурсивный обход

254
finder.sh Executable file
View File

@@ -0,0 +1,254 @@
#!/bin/bash
# Флаги
VERBOSE=0
SHOW_PATHS=0
RECURSIVE=1
TARGET_EXT=""
INPUT_DIR="."
NO_DEFAULT_EXCLUDES=0
EXCLUDE_DIRS=()
EXCLUDE_EXTS=()
# Функция помощи
show_help() {
echo "Использование: $0 [OPTIONS] [EXTENSION]"
echo ""
echo "Опции:"
echo " -i, --input DIR Входная директория (по умолчанию текущая)"
echo " -v, --verbose Подробный вывод"
echo " -p, --paths Показать пути к файлам (вместо статистики)"
echo " -n, --no-recursive Только текущая директория"
echo " -r, --recursive Рекурсивный обход (по умолчанию)"
echo " -e, --exclude-dir DIR Исключить директорию (можно несколько раз)"
echo " --exclude-ext EXT Исключить расширение файла (можно несколько раз)"
echo " -D, --no-default-excludes Не исключать .git (по умолчанию .git исключается)"
echo " -h, --help Показать эту справку"
echo ""
echo "Примеры:"
echo " $0 # Статистика всех файлов"
echo " $0 .txt # Статистика txt файлов"
echo " $0 -p .py # Показать все пути к .py файлам"
echo " $0 -p # Показать пути ко всем файлам"
echo " $0 -v # Подробная статистика всех файлов"
echo " $0 -n # Только в текущей директории"
echo " $0 -e build --exclude-ext log # Исключить папку build и .log файлы"
echo " $0 -D # Отключить встроенное исключение .git"
echo " $0 -i ~/projects -p .py # Показать .py файлы в указанной папке"
}
# Парсинг аргументов
while [[ $# -gt 0 ]]; do
case $1 in
-v|--verbose)
VERBOSE=1
shift
;;
-p|--paths)
SHOW_PATHS=1
shift
;;
-r|--recursive)
RECURSIVE=1
shift
;;
-n|--no-recursive)
RECURSIVE=0
shift
;;
-i|--input)
if [[ -z "$2" ]]; then
echo "Ошибка: опция -i требует аргумент"
exit 1
fi
INPUT_DIR="$2"
shift 2
;;
-e|--exclude-dir)
if [[ -z "$2" ]]; then
echo "Ошибка: опция -e требует аргумент"
exit 1
fi
EXCLUDE_DIRS+=("$2")
shift 2
;;
--exclude-ext)
if [[ -z "$2" ]]; then
echo "Ошибка: опция --exclude-ext требует аргумент"
exit 1
fi
EXCLUDE_EXTS+=("$2")
shift 2
;;
-D|--no-default-excludes)
NO_DEFAULT_EXCLUDES=1
shift
;;
-h|--help)
show_help
exit 0
;;
-*)
echo "Ошибка: Неизвестная опция $1"
show_help
exit 1
;;
*)
TARGET_EXT="$1"
shift
;;
esac
done
# Проверка существования входной директории
if [[ ! -d "$INPUT_DIR" ]]; then
echo "Ошибка: Директория '$INPUT_DIR' не существует"
exit 1
fi
# Переход в рабочую директорию
CURRENT_DIR="$(pwd)"
cd "$INPUT_DIR" || {
echo "Ошибка: Не удалось перейти в директорию '$INPUT_DIR'"
exit 1
}
WORK_DIR="$(pwd)"
# Очистка расширения: убираем ведущую точку, если есть
clean_ext() {
local ext="$1"
ext="${ext#.}"
echo "$ext"
}
# Функция получения расширения файла (без точки)
get_extension() {
local file="$1"
local filename=$(basename -- "$file")
local ext="${filename##*.}"
if [[ "$ext" == "$filename" ]]; then
echo "no_extension"
else
echo "$ext"
fi
}
# Основная функция поиска и вывода
process_files() {
# Построение массива аргументов для find
local find_args=(".")
local has_target=0
# Глубина
if [[ $RECURSIVE -eq 0 ]]; then
find_args+=("-maxdepth" "1")
fi
# Только файлы
find_args+=("-type" "f")
# Стандартные исключения (только .git)
if [[ $NO_DEFAULT_EXCLUDES -eq 0 ]]; then
find_args+=("-not" "-path" "./.git/*" "-not" "-path" "./.git")
fi
# Пользовательские исключения директорий
for dir in "${EXCLUDE_DIRS[@]}"; do
dir="${dir%/}" # убрать слеш в конце
local clean_dir="${dir#./}"
# Исключаем саму директорию и всё внутри неё
find_args+=("-not" "-path" "./$clean_dir" "-not" "-path" "./$clean_dir/*")
# На всякий случай, если вложена где-то ещё
find_args+=("-not" "-path" "*/$clean_dir/*" "-not" "-path" "*/$clean_dir")
done
# Фильтр по целевому расширению
if [[ -n "$TARGET_EXT" ]]; then
has_target=1
if [[ "$TARGET_EXT" == "no_extension" ]]; then
find_args+=("!" "-name" "*.*")
else
local ext_clean=$(clean_ext "$TARGET_EXT")
find_args+=("-name" "*.$ext_clean")
fi
fi
# Исключение расширений
for ext in "${EXCLUDE_EXTS[@]}"; do
ext=$(clean_ext "$ext")
find_args+=("-not" "-name" "*.$ext")
done
# Вывод информации при verbose
if [[ $VERBOSE -eq 1 ]]; then
echo "Рабочая директория: $WORK_DIR"
echo "Режим: $([[ $SHOW_PATHS -eq 1 ]] && echo 'Показ путей' || echo 'Статистика')"
echo "Рекурсивно: $([[ $RECURSIVE -eq 1 ]] && echo 'Да' || echo 'Нет')"
echo "Стандартные исключения: $([[ $NO_DEFAULT_EXCLUDES -eq 0 ]] && echo '.git' || echo 'Нет')"
[[ -n "$TARGET_EXT" ]] && echo "Целевое расширение: $TARGET_EXT"
[[ ${#EXCLUDE_DIRS[@]} -gt 0 ]] && echo "Исключаемые папки: ${EXCLUDE_DIRS[*]}"
[[ ${#EXCLUDE_EXTS[@]} -gt 0 ]] && echo "Исключаемые расширения: ${EXCLUDE_EXTS[*]}"
echo ""
fi
if [[ $SHOW_PATHS -eq 1 ]]; then
# Режим вывода путей
if [[ -n "$TARGET_EXT" ]]; then
echo "Пути к .$(clean_ext "$TARGET_EXT") файлам:"
else
echo "Пути ко всем файлам:"
fi
echo "=========================="
local count=0
while IFS= read -r -d '' file; do
echo "${file#./}"
((count++))
done < <(find "${find_args[@]}" -print0 2>/dev/null)
echo "-------------------------"
echo "Найдено файлов: $count"
else
# Режим статистики
declare -A stats
while IFS= read -r -d '' file; do
local ext
if [[ -n "$TARGET_EXT" ]]; then
ext=$(clean_ext "$TARGET_EXT")
else
ext=$(get_extension "$file")
fi
((stats["$ext"]++))
done < <(find "${find_args[@]}" -print0 2>/dev/null)
if [[ -n "$TARGET_EXT" ]]; then
local t=$(clean_ext "$TARGET_EXT")
echo "Статистика .$t файлов:"
echo "============================="
echo "$t: ${stats[$t]:-0}"
else
echo "Статистика файлов:"
echo "================="
local total_files=0
# Сортировка расширений по убыванию количества
for ext in "${!stats[@]}"; do
printf "%s %d\n" "$ext" "${stats[$ext]}"
done | sort -k2 -nr | while read ext count; do
printf "%-15s %d\n" "$ext" "$count"
done
# Суммируем (цикл выше в подоболочке, поэтому считаем отдельно)
for count in "${stats[@]}"; do
((total_files += count))
done
echo "-------------------------"
echo "Всего файлов: $total_files"
echo "Уникальных расширений: ${#stats[@]}"
fi
fi
}
# Запуск обработки
process_files
# Возврат в исходную директорию
if [[ "$CURRENT_DIR" != "$WORK_DIR" ]]; then
cd "$CURRENT_DIR" || exit 1
fi