We write a Bash script for building a directory tree for a repository in the
Markdown file. We use only Bash builtin tools and basic Linux software — ls
,
sed
, tr
and printf
— without additional programs. The obtained file
DIRECTORY_TREE.md
is useful in the web-interface to navigate through the objects of the repository.
We create a recursive function and use it to bypass all files and directories of the repository,
excluding the list from .gitignore
— we build a directory structure in the form of a tree. We
output the elements as links <a>
, collapse folders with one nested element into one line, place
the constructed tree in a container <pre>
and add the header — as a result, we get a short and
concise Markdown file with links.
#!/bin/bash
# directory tree with links
function directory_tree {
# arguments
local path="$1"
local head="$2"
local tail="$3"
# get directory contents
if [ -d "$path" ]; then
# first uppercase letters, then lowercase, first directories, then files
ls_sorted="LC_COLLATE=C ls -A --group-directories-first $exclusions $path"
# sorted array of files and directories
local list && readarray -t list < <(eval "$ls_sorted")
# length of array
local size=${#list[@]}
# skip empty directory
[ "$size" == 0 ] && return
fi
# prefix of current element, collapse singletons into one line
[ "$4" == "one" ] && printf '%s' "/" || printf '\n%s' "$head"
# current element of the tree — relative hyperlink
printf '%s' "<a href='${path#*/}'>${path##*/}</a>"
# recursive calls for subdirectories
if [ -d "$path" ]; then
local i # counter
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
}
# line of exclusions for "ls" from the list of untracked files ".gitignore"
exclusions="-I'.git' $(sed -E "s|^(.*)$|-I'\1'|" .gitignore | tr '\n' ' ')"
# place the tree in a container, add a header and output to a file
printf '%s\n' "## Directory tree" "" "<pre>" \
"$(directory_tree . | grep '\S')" "</pre>" >DIRECTORY_TREE.md
Run the script in the root of the repository and save the obtained file.
© Golovin G.G., Code with comments, translation from Russian, 2023