diff --git a/README.md b/README.md index 7718c9f..32f8192 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,8 @@ # linux_tools -Инструменты для Линукс \ No newline at end of file +Инструменты для Линукс + +использование всех инструментов: chmod +x combine.sh + +# combine.sh +Объединяет содержимое текстовых файлов из указанной директории в один файл. Удобно для подготовки контекста для AI, анализа кода или создания резюме проекта. diff --git a/combine.sh b/combine.sh new file mode 100755 index 0000000..ba8280a --- /dev/null +++ b/combine.sh @@ -0,0 +1,215 @@ +#!/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