All in one output file

This commit is contained in:
2026-01-27 16:16:19 +07:00
parent fa33c3d19d
commit 6ae9a00f3a

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env bash
# projdump.sh dump project structure and source code into text files
# projdump.sh - dump project structure and source code into a single text file
set -euo pipefail
@@ -7,9 +7,8 @@ usage() {
cat >&2 <<EOF
Использование: $0 <директория>
Создаёт два файла:
<basename>-tree.txt — дерево проекта (через tree)
<basename>-code.txt — содержимое всех исходных файлов
Создаёт один файл:
<basename>-dump.txt — дерево проекта + содержимое исходных файлов
Игнорирует типичные артефакты сборки, кэши, IDE-файлы и зависимости.
@@ -30,13 +29,11 @@ if [[ ! -d "$TARGET_DIR" ]]; then
exit 1
fi
# Привести к абсолютному пути для надёжности
# Привести к абсолютному пути
TARGET_DIR="$(cd "$TARGET_DIR" && pwd)"
# Имя базовой директории
BASENAME=$(basename "$TARGET_DIR")
# Проверка зависимостей
# Проверка зависимости
if ! command -v tree >/dev/null 2>&1; then
echo "Ошибка: требуется утилита 'tree'. Установите её (например, apt install tree)." >&2
exit 1
@@ -137,10 +134,9 @@ IGNORE_LIST=(
"*.tfvars"
)
# === Подготовка аргументов для find ===
# === Подготовка find-аргументов ===
FIND_IGNORE_ARGS=()
for pat in "${IGNORE_LIST[@]}"; do
# Для шаблонов с /* или * внутри — используем -name или -path соответственно
if [[ "$pat" == */* ]]; then
FIND_IGNORE_ARGS+=(-o -path "*/$pat")
else
@@ -148,23 +144,15 @@ for pat in "${IGNORE_LIST[@]}"; do
fi
done
# Строим команду find: пропускаем игнорируемые, печатаем остальные файлы
# \( -false ... \) гарантирует корректную логику без начального -o
FIND_CMD=(find "$TARGET_DIR" \( -false "${FIND_IGNORE_ARGS[@]}" \) -prune -o -type f -print0)
# === Паттерны для tree (только имена, без путей; tree использует glob-паттерны через |) ===
# === Подготовка шаблонов для tree ===
TREE_IGNORE_PATTERNS=""
for i in "${!IGNORE_LIST[@]}"; do
pat="${IGNORE_LIST[i]}"
# tree не поддерживает пути — только имена файлов/директорий
# поэтому берём только basename шаблона, если он содержит /
if [[ "$pat" == */* ]]; then
# Например, ".github/workflows" → игнорируем только ".github"
base_pat="${pat%%/*}"
else
base_pat="$pat"
fi
# Удаляем звёздочки для tree? Нет — tree поддерживает * в -I
for pat in "${IGNORE_LIST[@]}"; do
# tree работает только с именами, не путями → берём базовое имя
base_pat="${pat%%/*}"
# Убираем звёздочки? Нет — tree поддерживает glob, но * может мешать.
# Однако мы оставляем как есть, т.к. tree -I '*.pyc|node_modules' — нормально.
if [[ -z "$TREE_IGNORE_PATTERNS" ]]; then
TREE_IGNORE_PATTERNS="$base_pat"
else
@@ -172,21 +160,25 @@ for i in "${!IGNORE_LIST[@]}"; do
fi
done
# === Сбор кода ===
OUTPUT_FILE="${BASENAME}-dump.txt"
{
echo "========================================"
echo "PROJECT STRUCTURE (via tree)"
echo "========================================"
tree -I "$TREE_IGNORE_PATTERNS" "$TARGET_DIR"
echo -e "\n\n"
echo "========================================"
echo "SOURCE CODE CONTENTS"
echo "========================================"
while IFS= read -r -d '' file; do
echo "========================================"
echo "----------------------------------------"
echo "// FILE: $file"
echo "========================================"
echo "----------------------------------------"
cat "$file"
echo -e "\n\n"
echo -e "\n"
done < <("${FIND_CMD[@]}")
} > "${BASENAME}-code.txt"
# === Построение дерева ===
tree -I "$TREE_IGNORE_PATTERNS" "$TARGET_DIR" > "${BASENAME}-tree.txt"
echo "Готово:"
echo " Дерево: ${BASENAME}-tree.txt"
echo " Код: ${BASENAME}-code.txt"
} > "$OUTPUT_FILE"
echo "Готово: $OUTPUT_FILE"