Напишем скрипт Bash для построения дерева каталогов для репозитория в файле
Markdown. Будем использовать только встроенные средства Bash и базовое ПО Linux
— ls
, sed
, tr
и printf
— без дополнительных программ. Полученный файл
DIRECTORY_TREE.md
пригодится в вёб-интерфейсе для навигации по объектам репозитория.
Создаём рекурсивную функцию и с её помощью обходим все файлы и каталоги репозитория, за
исключением списка из .gitignore
— строим структуру каталогов в форме дерева. Выводим
элементы в виде ссылок <a>
, сворачиваем папки с одним вложенным элементом в одну строку,
помещаем собранное дерево в контейнер <pre>
и добавляем заголовок — в результате получаем
краткий и лаконичный файл Markdown со ссылками.
#!/bin/bash
# дерево каталогов со ссылками
function directory_tree {
# аргументы
local path="$1"
local head="$2"
local tail="$3"
# получить содержимое каталога
if [ -d "$path" ]; then
# сначала заглавные буквы, потом строчные, сначала каталоги, потом файлы
ls_sorted="LC_COLLATE=C ls -A --group-directories-first $exclusions $path"
# отсортированный массив файлов и каталогов
local list && readarray -t list < <(eval "$ls_sorted")
# длина массива
local size=${#list[@]}
# пропустить пустой каталог
[ "$size" == 0 ] && return
fi
# префикс текущего элемента, сворачивать синглтоны в одну строку
[ "$4" == "one" ] && printf '%s' "/" || printf '\n%s' "$head"
# текущий элемент дерева — относительная гиперссылка
printf '%s' "<a href='${path#*/}'>${path##*/}</a>"
# рекурсивные вызовы для подкаталогов
if [ -d "$path" ]; then
local i # счётчик
for ((i = 0; i < size; i++)); do
if ((size == 1)); then
directory_tree "$path/${list[$i]}" "$tail" "$tail" "one"
elif ((i < size - 1)); then
directory_tree "$path/${list[$i]}" "$tail├─ " "$tail│ "
else
directory_tree "$path/${list[$i]}" "$tail└─ " "$tail "
fi
done
fi
}
# строка исключений для "ls" из списка неотслеживаемых файлов ".gitignore"
exclusions="-I'.git' $(sed -E "s|^(.*)$|-I'\1'|" .gitignore | tr '\n' ' ')"
# помещаем дерево в контейнер, добавляем заголовок и выводим в файл
printf '%s\n' "## Дерево каталогов" "" "<pre>" \
"$(directory_tree . | grep '\S')" "</pre>" >DIRECTORY_TREE.md
Запускаем скрипт в корне репозитория и сохраняем полученный файл.
© Головин Г.Г., Код с комментариями, 2023