216 lines
6.9 KiB
Bash
Executable File
216 lines
6.9 KiB
Bash
Executable File
#!/bin/bash
|
||
|
||
# Название выходного файла по умолчанию
|
||
OUTPUT_FILE="combined_files.txt"
|
||
# Директория по умолчанию
|
||
INPUT_DIR="."
|
||
# Флаги
|
||
VERBOSE=0
|
||
RECURSIVE=1
|
||
# Массив для исключений
|
||
EXCLUDE_PATHS=()
|
||
|
||
# Функция для показа помощи
|
||
show_help() {
|
||
echo "Использование: $0 [OPTIONS]"
|
||
echo ""
|
||
echo "Опции:"
|
||
echo " -o, --output FILE Выходной файл (по умолчанию: combined_files.txt)"
|
||
echo " -i, --input DIR Входная директория (по умолчанию: текущая)"
|
||
echo " -e, --exclude PATH Исключить путь (можно указать несколько раз)"
|
||
echo " -r, --recursive Рекурсивный поиск (включено по умолчанию)"
|
||
echo " -n, --no-recursive Не рекурсивный поиск"
|
||
echo " -v, --verbose Подробный вывод"
|
||
echo " -h, --help Показать эту справку"
|
||
echo ""
|
||
echo "Примеры:"
|
||
echo " $0 -v -o result.txt"
|
||
echo " $0 -i ~/projects -o /tmp/combined.txt"
|
||
echo " $0 -e venv -e foto -e node_modules"
|
||
echo " $0 --no-recursive --verbose -e temp"
|
||
}
|
||
|
||
# Парсинг аргументов командной строки
|
||
while [[ $# -gt 0 ]]; do
|
||
case $1 in
|
||
-o|--output)
|
||
OUTPUT_FILE="$2"
|
||
shift 2
|
||
;;
|
||
-i|--input)
|
||
INPUT_DIR="$2"
|
||
shift 2
|
||
;;
|
||
-e|--exclude)
|
||
EXCLUDE_PATHS+=("$2")
|
||
shift 2
|
||
;;
|
||
-r|--recursive)
|
||
RECURSIVE=1
|
||
shift
|
||
;;
|
||
-n|--no-recursive)
|
||
RECURSIVE=0
|
||
shift
|
||
;;
|
||
-v|--verbose)
|
||
VERBOSE=1
|
||
shift
|
||
;;
|
||
-h|--help)
|
||
show_help
|
||
exit 0
|
||
;;
|
||
*)
|
||
echo "Ошибка: Неизвестный параметр $1"
|
||
echo "Используйте $0 --help для справки"
|
||
exit 1
|
||
;;
|
||
esac
|
||
done
|
||
|
||
# Проверка существования входной директории
|
||
if [[ ! -d "$INPUT_DIR" ]]; then
|
||
echo "Ошибка: Директория '$INPUT_DIR' не существует"
|
||
exit 1
|
||
fi
|
||
|
||
# Проверка на запись в выходной файл
|
||
if touch "$OUTPUT_FILE" 2>/dev/null; then
|
||
rm -f "$OUTPUT_FILE"
|
||
else
|
||
echo "Ошибка: Нет прав для записи в '$OUTPUT_FILE'"
|
||
exit 1
|
||
fi
|
||
|
||
# Запоминаем текущую директорию для возврата
|
||
CURRENT_DIR="$(pwd)"
|
||
|
||
# Переход в входную директорию если она указана не как текущая
|
||
if [[ "$INPUT_DIR" != "." ]]; then
|
||
cd "$INPUT_DIR" || {
|
||
echo "Ошибка: Не удалось перейти в директорию '$INPUT_DIR'"
|
||
exit 1
|
||
}
|
||
fi
|
||
|
||
# Очищаем выходной файл
|
||
> "$OUTPUT_FILE"
|
||
|
||
# Счетчики
|
||
total_files=0
|
||
processed_files=0
|
||
skipped_files=0
|
||
|
||
# Вывод информации о запуске
|
||
if [[ $VERBOSE -eq 1 ]]; then
|
||
echo "Запуск combine.sh с параметрами:"
|
||
echo " Входная директория: $(pwd)"
|
||
echo " Выходной файл: $OUTPUT_FILE"
|
||
echo " Рекурсивный поиск: $([[ $RECURSIVE -eq 1 ]] && echo 'Да' || echo 'Нет')"
|
||
if [[ ${#EXCLUDE_PATHS[@]} -gt 0 ]]; then
|
||
echo " Исключения: ${EXCLUDE_PATHS[*]}"
|
||
fi
|
||
echo ""
|
||
fi
|
||
|
||
# Функция для обработки файлов
|
||
process_files() {
|
||
local find_cmd="find . -type f"
|
||
|
||
# Если не рекурсивно, ищем только в текущей директории
|
||
if [[ $RECURSIVE -eq 0 ]]; then
|
||
find_cmd="find . -maxdepth 1 -type f"
|
||
fi
|
||
|
||
# Добавляем стандартные исключения
|
||
find_cmd="$find_cmd \
|
||
-not -path \"./venv/*\" \
|
||
-not -path \"*/venv/*\" \
|
||
-not -path \"*/__pycache__/*\" \
|
||
-not -path \"*cache*\" \
|
||
-not -path \"*.pyc\" \
|
||
-not -path \"db.*\" \
|
||
-not -path \"*.lock\" \
|
||
-not -path \"*.git/*\" \
|
||
-not -path \"*.db\" \
|
||
-not -path \"*.pack\" \
|
||
-not -path \"*/node_modules/*\" \
|
||
-not -path \"./$OUTPUT_FILE\""
|
||
|
||
# Добавляем пользовательские исключения
|
||
for exclude in "${EXCLUDE_PATHS[@]}"; do
|
||
# Убираем начальные ./ если есть
|
||
exclude="${exclude#./}"
|
||
find_cmd="$find_cmd -not -path \"./$exclude\" -not -path \"./$exclude/*\" -not -path \"*/$exclude/*\""
|
||
done
|
||
|
||
find_cmd="$find_cmd 2>/dev/null"
|
||
|
||
# Временный файл для результатов find
|
||
local temp_file=$(mktemp)
|
||
|
||
# Выполняем поиск и сохраняем во временный файл
|
||
eval "$find_cmd" > "$temp_file"
|
||
|
||
# Обрабатываем файлы
|
||
while IFS= read -r file; do
|
||
[[ -z "$file" ]] && continue
|
||
|
||
((total_files++))
|
||
|
||
# Пропускаем бинарные файлы
|
||
if file "$file" | grep -q "text"; then
|
||
# Получаем относительный путь файла
|
||
relative_path="${file#./}"
|
||
|
||
if [[ $VERBOSE -eq 1 ]]; then
|
||
echo "Добавляем: $relative_path"
|
||
fi
|
||
|
||
# Добавляем разделитель с именем файла в выходной файл
|
||
{
|
||
echo "# ========================================="
|
||
echo "# Файл: $relative_path"
|
||
echo "# ========================================="
|
||
echo ""
|
||
cat "$file" 2>/dev/null
|
||
echo ""
|
||
echo ""
|
||
} >> "$OUTPUT_FILE"
|
||
|
||
((processed_files++))
|
||
else
|
||
if [[ $VERBOSE -eq 1 ]]; then
|
||
echo "Пропускаем (бинарный): ${file#./}"
|
||
fi
|
||
((skipped_files++))
|
||
fi
|
||
done < "$temp_file"
|
||
|
||
# Удаляем временный файл
|
||
rm -f "$temp_file"
|
||
}
|
||
|
||
# Запускаем обработку
|
||
process_files
|
||
|
||
# Возвращаемся в исходную директорию если нужно
|
||
if [[ "$INPUT_DIR" != "." ]]; then
|
||
cd "$CURRENT_DIR" || exit 1
|
||
fi
|
||
|
||
# Итоговый отчет
|
||
echo "Готово!"
|
||
echo "Обработано файлов: $processed_files из $total_files"
|
||
if [[ $skipped_files -gt 0 ]]; then
|
||
echo "Пропущено бинарных файлов: $skipped_files"
|
||
fi
|
||
if [[ ${#EXCLUDE_PATHS[@]} -gt 0 ]]; then
|
||
echo "Исключено путей: ${#EXCLUDE_PATHS[@]}"
|
||
fi
|
||
echo "Результат в: $OUTPUT_FILE"
|
||
if [[ "$INPUT_DIR" != "." ]]; then
|
||
echo "Исходная директория: $INPUT_DIR"
|
||
fi
|