5/jekyll_site/en/2023/08/04/directory-tree.md
2024-12-29 10:39:46 +03:00

2.9 KiB
Raw Blame History

title description sections tags canonical_url url_translated title_translated date lang
Directory tree with links We write a Bash script for building a directory tree for a repository in the Markdown file. We use only Bash tools and basic Linux software without additional.
Recursion
File processing
Web-navigation
linux
bash
markdown
html
structure
folders
files
references
sorting
/en/2023/08/04/directory-tree.html /ru/2023/08/03/directory-tree.html Дерево каталогов со ссылками 2023.08.04 en

We write a Bash script for building a directory tree for a repository in the Markdown file. We use only Bash tools and basic Linux software — ls, sed, tr and echo — without additional programs. The obtained file [DIRECTORY_TREE.md]({{ site.homepage_url }} "{{ site.homepage_name }}") will be used 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
# sorted list of files and directories
function list_directory_contents {
  # first uppercase letters, then lowercase, first directories, then files
  eval "LC_COLLATE=C ls -A --group-directories-first $exclusions $1"
}
# directory tree with links
function directory_tree {
  # arguments
  local path="$1"
  local head="$2"
  local tail="$3"
  # prefix for current element
  [ "one" == "$4" ] && printf '%s' "/" || printf '\n%s' "$head"
  # current element of the tree
  printf '%s' "<a href='${path#*/}'>${path##*/}</a>"
  # recursive calls for subdirectories
  if [ -d "$path" ]; then
    local list # array of files and directories
    readarray -t list < <(list_directory_contents "$path")
    local size=${#list[@]} # length of array
    local i # counter
    for ((i = 0; i < size; i++)); do
      if [ -z "${list[$i]}" ]; then
        continue # skip empty directory
      elif ((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.