Obsidian/reddup.sh

180 lines
6.0 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
# ------------------------------------------------------------------
# Author: ChatGPT
# Generated on: $(date '+%Y-%m-%d')
#
# This script recursively creates or updates a table-of-contents README
# file in each non-hidden directory. The file is named "Folder Name - README.md".
#
# Each README includes:
# - An author/date header.
# - A header with the folder's name.
# - An alphabetically sorted list of immediate subdirectories, with links
# to that subdirectorys own README.
# - An alphabetically sorted list of immediate files (excluding the generated README).
# - A "Summary" section with a short description generated by an LLM (using llama3.2:latest).
#
# Hidden directories (or any directory under a hidden parent such as .git) are skipped.
#
# The script only updates a README if the static content (header, subdirectories and files)
# changes. The LLM summary output is excluded from the diff check.
#
# Progress is printed as "[x/y] Updated: {dir}" or "[x/y] No change: {dir}".
# ------------------------------------------------------------------
# Set the base directory (change "." if necessary)
base_dir="."
# Build an array of directories to process.
dirs=()
while IFS= read -r -d '' dir; do
# Skip directories that are hidden or inside a hidden parent (like .git)
if [[ "$(basename "$dir")" == .* ]] || [[ "$dir" == *"/.git"* ]] || [[ "$dir" == *"/.obsidian"* ]]; then
continue
fi
dirs+=( "$dir" )
done < <(find "$base_dir" -type d -print0)
total=${#dirs[@]}
count=0
for dir in "${dirs[@]}"; do
count=$((count+1))
# For the top-level directory, use the actual name from $PWD; otherwise, use the directory's basename.
if [ "$dir" = "$base_dir" ]; then
base=$(basename "$PWD")
else
base=$(basename "$dir")
fi
# Define the path for the README file: "Folder Name - README.md"
readme="$dir/${base} - README.md"
# Create a temporary file to hold the new static content.
tmp_static=$(mktemp)
{
echo "# Table of Contents for ${base}"
echo ""
} > "$tmp_static"
#########################
# Process Subdirectories
#########################
subdirs=()
while IFS= read -r -d '' subdir; do
sub_basename=$(basename "$subdir")
if [ -n "$sub_basename" ]; then
subdirs+=( "$sub_basename" )
fi
done < <(find "$dir" -mindepth 1 -maxdepth 1 -type d ! -name '.*' -print0)
if [ ${#subdirs[@]} -gt 0 ]; then
mapfile -t sorted_subdirs < <(printf "%s\n" "${subdirs[@]}" | sort)
echo "## Subdirectories" >> "$tmp_static"
for sub in "${sorted_subdirs[@]}"; do
# Link format: [[Subfolder/Subfolder - README]]
line="- [[${sub}/${sub} - README]]"
printf "%s\n" "$line" >> "$tmp_static"
done
echo "" >> "$tmp_static"
fi
#################
# Process Files
#################
files=()
while IFS= read -r -d '' file; do
fbase=$(basename "$file")
if [ -n "$fbase" ]; then
files+=( "$fbase" )
fi
done < <(find "$dir" -mindepth 1 -maxdepth 1 -type f ! -path "$readme" -print0)
if [ ${#files[@]} -gt 0 ]; then
mapfile -t sorted_files < <(printf "%s\n" "${files[@]}" | sort)
echo "## Files" >> "$tmp_static"
for f in "${sorted_files[@]}"; do
line="- [[${f}]]"
printf "%s\n" "$line" >> "$tmp_static"
done
echo "" >> "$tmp_static"
fi
# Determine if the static content has changed.
static_changed=1
if [ -f "$readme" ]; then
# Extract the static portion from the existing README (everything before "## Summary")
existing_static=$(sed '/^## Summary/,$d' "$readme")
new_static=$(cat "$tmp_static")
if [ "$existing_static" = "$new_static" ]; then
static_changed=0
fi
fi
if [ $static_changed -eq 0 ]; then
echo "[$count/$total] No change: $dir"
rm "$tmp_static"
continue
fi
#################
# Query LLM for Summary
#################
echo "Creating summary..."
# Define file extensions considered to be text-based.
# You can easily edit this array to add or remove extensions.
TEXT_EXTENSIONS=( "*.md" "*.rs" "*.hs" "*.py" "*.txt" "*.m" )
# Build an array of find conditions.
# For each extension, we add "-iname <extension>" to the array.
FIND_CONDITIONS=()
for ext in "${TEXT_EXTENSIONS[@]}"; do
FIND_CONDITIONS+=( -iname "$ext" -o )
done
# Remove the last extra '-o'
unset 'FIND_CONDITIONS[${#FIND_CONDITIONS[@]}-1]'
# Now use find with these conditions.
# Pull in the content of all markdown files in this folder (excluding the generated README)
folder_md=$(find "$dir" -maxdepth 1 -type f \( "${FIND_CONDITIONS[@]}" \) ! -path "$readme" \
-exec sh -c 'for file; do
echo "=======$file========="
cat "$file"
echo "========end $file========"
echo ""
done' sh {} +)
prompt="You are creating a description for a README file in my Obsidian notes database. Below you will find two items. Item number 1 is a table of contents of what is in the folder of the README file. Item number 2 is the contents of all of the text based files within that folder. Based on this information, create a description of what is inside the folder, as if you were telling yourself what is in there. Be concise, to the point, and do not excessively speculate. Your result will be put into a Markdown file, where you can use [[wikilinks]] and other markdown syntax. When you use the name of a file in a description, put it in a [[wikilink]]. Thanks!
Item 1:
$(cat "$tmp_static")
Item 2:
$folder_md"
echo ""
echo "Prompt:"
echo "================="
echo $prompt
summary=$(ollama run llama3.2 "$prompt")
echo ""
echo "Summary:"
echo "================="
echo $summary
# Build the full new content: static portion + summary section.
{
cat "$tmp_static"
echo "## Summary"
echo "$summary"
echo ""
echo "Generated by llama3.2:latest"
} > "$readme"
rm "$tmp_static"
echo "[$count/$total] Updated: $dir"
done