4 KiB
title | description | sections | tags | canonical_url | url_translated | title_translated | date | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Дерево каталогов со ссылками | Напишем скрипт Bash для построения дерева каталогов для репозитория в файле Markdown. Будем использовать только средства Bash и базовое ПО Linux без... |
|
|
/ru/2023/08/03/directory-tree.html | /en/2023/08/04/directory-tree.html | Directory tree with links | 2023.08.03 |
Напишем скрипт Bash для построения дерева каталогов для репозитория в
файле Markdown. Будем использовать только средства Bash и базовое ПО Linux
— ls
, sed
, tr
и echo
— без дополнительных программ. Полученный файл
[DIRECTORY_TREE.md
]({{ site.homepage_url }} "{{ site.homepage_name }}")
будем использовать в вёб-интерфейсе для навигации по объектам репозитория.
Создаём рекурсивную функцию и с её помощью обходим все файлы и каталоги репозитория, за
исключением списка из .gitignore
— строим структуру каталогов в форме дерева. Выводим
элементы в виде ссылок <a>
, сворачиваем папки с одним вложенным элементом в одну строку,
помещаем собранное дерево в контейнер <pre>
и добавляем заголовок — в результате получаем
краткий и лаконичный файл Markdown со ссылками.
#!/bin/bash
# отсортированный список файлов и каталогов
function list_directory_contents {
# сначала заглавные буквы, потом строчные, сначала каталоги, потом файлы
eval "LC_COLLATE=C ls -A --group-directories-first $exclusions $1"
}
# дерево каталогов со ссылками
function directory_tree {
# аргументы
local path="$1"
local head="$2"
local tail="$3"
# префикс для текущего элемента
if [ "one" == "$4" ]; then
echo -n "/"
else
echo -ne "\n$head"
fi
# текущий элемент дерева
echo -n "<a href='${path#*/}'>${path##*/}</a>"
# рекурсивные вызовы для подкаталогов
if [ -d "$path" ]; then
local list # массив файлов и каталогов
readarray -t list <<<"$(list_directory_contents "$path")"
local len=${#list[@]} # размер массива
local i # счётчик
for ((i = 0; i < len; i++)); do
if [ -z "${list[$i]}" ]; then
continue # пропустить пустой каталог
elif ((len == 1)); then
directory_tree "$path/${list[$i]}" "$tail" "$tail" "one"
elif ((i < len - 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 's/^/ -I "/;s/$/"/' .gitignore | tr -d '\n')"
# помещаем дерево в контейнер, добавляем заголовок и выводим в файл
{
echo "## Дерево каталогов"
echo -ne "\n<pre>"
directory_tree .
echo -e "\n</pre>"
} >DIRECTORY_TREE.md
Запускаем скрипт в корне репозитория и сохраняем полученный файл.