Commit d0477e94 authored by prx's avatar prx

update 0.8

parent c2a962ec
This diff is collapsed.
#!/bin/sh
# sw - suckless webframework - 2012 - MIT License - nibble <develsec.org>
# swx - Modified by Thuban - 2016 - MIT License - <thuban@yeuxdelibad.net>
VERSION=0.4
VERSION=0.8
preparebar() {
# $1 - bar length
# $2 - bar char
barlen=$1
barspaces=$(printf "%*s" "$1")
barchars=$(printf "%*s" "$1" | tr ' ' "$2")
}
progressbar() {
# $1 - number (-1 for clearing the bar)
# $2 - max number
if [ $1 -eq -1 ]; then
printf "\r $barspaces\r"
else
barch=$(($1*barlen/$2))
barsp=$((barlen-barch))
printf "\r[%.${barch}s%.${barsp}s]\r" "$barchars" "$barspaces"
fi
}
register() {
echo $1 >> "$LOG"
}
isfresher() {
if [ -z $(uname |grep "BSD") ]; then
if [ ! -f "${2}" ]; then
register "$1"
return 0
elif [ $(stat "${1}" -c %Y) -gt $(stat "${2}" -c %Y) ]; then
return 0
else
return 1
fi
else
if [ ! -f "${2}" ]; then
register "$1"
return 0
elif [ $(stat -f %m "${1}") -gt $(stat -f %m "${2}") ]; then
return 0
else
return 1
fi
fi
}
domenulist() {
echo "<p>Pages présentes dans ce dossier :</p>"
echo "<ul>"
for f in $(ls $(dirname $1)/) ; do
sw_filter $i && continue
[ -n "$(echo $f | grep 'index.$EXT$')" ] && continue
echo "<li><a href=\"$(echo $f | sed -e "s,$EXT$,.html,g") \">$(echo $f | sed -e 's/\..*$//' -e 's/_/ /g')</a></li>"
done
echo "</ul>"
}
sw_filter() {
for b in $BL; do
[ "$b" = "$1" ] && return 0
done
}
sw_main() {
if [ -z $(uname |grep "BSD") ]; then
if [ $(stat "$1" -c %s) -eq 0 ]; then
domenulist $1
else
$CONVERTER $1
fi
else
if [ $(stat -f %z "$1") -eq 0 ]; then
domenulist $1
else
$CONVERTER $1
fi
fi
}
sw_menu() {
echo "<ul>"
if [ "$(dirname $1)" != "$IDIR" ] ; then
echo "<li><a $( [ -n "$(echo $1 | grep index$EXT)" ] && echo "class=\"thisPage\" ") href=\"./index.html\">.</a></li>"
echo "<li><a href=\"../index.html\">..</a></li>"
fi
FILES=$(ls $(dirname $1) | sed -e "s,$EXT$,.html,g")
INAME=$(basename "$(echo $1 | sed -e 's/\..*$//' -e 's/_/ /g')")
for i in $FILES ; do
sw_filter $i && continue
NAME=$(echo $i | sed -e 's/\..*$//' -e 's/_/ /g')
[ -n "$(echo $i | grep 'index.html$')" ] && continue
#[ -z "$(echo $i | grep '\..*$')" ] && i="$i/index.html" # Pas d'extension : dossier
echo "<li><a $( [ "$INAME" = "$NAME" ] && echo "class=\"thisPage\" ") href=\"$i\">$NAME</a></li>"
done
echo "</ul>"
}
sw_page() {
PAGENAME=$(basename "$1" |sed -e 's/\..*$//' -e 's/_/ /g')
DIRNAME=$(basename "$(dirname "$1" |sed -e 's/_/ /g')")
# Header
cat << _header_
<!doctype html>
<html>
<head>
<title>${TITLE} | ${DIRNAME} - ${PAGENAME}</title>
$HEADER
</head>
<body>
<header>
<h1 class="headerTitle">
<a href="$(echo $1 | sed -e 's,[^/]*/,../,g' -e "s,[^/]*$EXT$,index.html,g")">${TITLE}</a>
</h1>
<div class="headerSubtitle"><a href="/">${SUBTITLE}</a></div>
</header>
_header_
# Menu
echo "<nav>"
sw_menu $1
echo "</nav>"
# Body
echo "<main>"
echo "$TOPTEMPLATE"
sw_main $1
echo "</main>"
echo "$BOTTOMTEMPLATE"
# Footer
cat << _footer_
<footer>
Le $(date +'%d/%m/%Y à %H:%M') avec <a href="http://yeuxdelibad.net/Programmation/swx.html">swx</a>
${FOOTER}
</footer>
</body>
</html>
_footer_
}
# Set input dir
IDIR="$(echo $1 | sed -e 's,/*$,,')"
if [ -z "$IDIR" ] || [ ! -d $IDIR ]; then
echo "swx - version $VERSION"
echo "Usage: swx [dir]"
exit 1
fi
# Load config file
echo "> Load configuration"
if [ ! -f $PWD/swx.conf ]; then
echo "Cannot find swx.conf in current directory"
if [ ! -f $PWD/swx.conf ] || [ ! -f $PWD/swx.template ]; then
echo "Cannot find swx.conf or swx.template in current directory"
exit 1
fi
. $PWD/swx.conf
. $PWD/swx.functions
echo "> Prepare output directory"
# Setup output dir structure
ODIR="$PWD/$(basename $IDIR).static"
mkdir -p $ODIR
# copy only if necessary
echo "> Copying files"
#cp -ur $IDIR/* $ODIR/
rsync -av $IDIR/ $ODIR/
# remove .EXT files
echo "> Removing useless files"
find $ODIR -iname "*$EXT" -exec rm '{}' \;
# Parse files
echo "> Generating html pages"
FILES=$(find $IDIR -iname "*$EXT" | sed -e 's,^\./,,')
NB=$(echo $FILES | wc -w)
COUNT=0
preparebar 50 "#"
for a in $FILES; do
b="$(echo ${a%.*}.html | sed "s;$IDIR;$ODIR;g")"
# process only new files
isfresher "${a}" "${b}"
if [ $? -eq 0 ]; then
sw_page "${a}" > "${b}";
fi
COUNT=$(($COUNT + 1))
# Progression
#COUNT=$(expr $COUNT + 1)
#PERC=$(expr $COUNT \* 100 / $NB )
#if [ $PERC -eq 0 ]; then
# PERC=1
#fi
progressbar $COUNT $NB
#BAR=$(echo "$FULLBAR" | cut -b -$PERC)
#echo -n "($COUNT/$NB) $PERC% |$BAR| \r"
done
echo "\n\n> Done! :)"
# Set input dir
setdirs "${1}"
if [ $# -eq 1 ]; then
start_time=$(date +%s)
generate
end_time=$(date +%s)
echo "Site generated in $(($end_time - $start_time))s."
fi
exit 0
## SWX Configuration
#
## Site title
TITLE="My amazing website"
SUBTITLE="It is so much amazing"
HOSTNAME="http://whereami.net"
# Files and pages you don't want to see in menus
BL="favicon.svg favicon.ico style.css robots.txt img"
TITLE="Example"
SUBTITLE="Example subtitle"
# Black list. Won't be shown in menu
BL="favicon.png style.css style.min.css robots.txt"
HOSTNAME="example.net"
PROTOCOL="https://"
# External apps
#CONVERTER="/usr/bin/markdown" # md handler
# example with txt2tags
CONVERTER='txt2tags -t html -H --no-toc -o -'
#EXT=".md" # extension of files to convert
EXT=".t2t" # extension of files to convert
# Maximum entries in RSS feed
MAX=20
# String to replace with new articles list
NEWSSTR="%%%BLOG%%%"
# LOG FILE
LOG=swx.log
#CONVERTER='txt2tags -t html -H -o -'
#CONVERTER='discount -f +pants,+del,+autolink'
CONVERTER='lowdown -D html-skiphtml -E smarty -d metadata'
# html you want in footer
FOOTER='
- <a href="/feed.xml">RSS</a> -
<a href="#topOfPage" title="top">↑ En haut</a>
'
# What you want in the header of you pages
HEADER='<link rel="icon" href="/favicon.png" type="image/png">
<meta charset="UTF-8">
<meta name="author" content="Xavier Cartron" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" href="/style.css">
'
# html code to include in every html pages
# things to put on every page BEFORE the content
TOPTEMPLATE='<a id="topOfPage"></a>'
# things to put on every page AFTER the content
BOTTOMTEMPLATE=""
EXT=".md" # extension of files to convert
#EXT=".t2t" # extension of files to convert
# facultative
#
## BLOG and ATOM
# Maximum entries in atom feed and blog first page
MAX=10
## BLOG
# String to replace with new articles list in first page
# if it's not present, nothing will be published as news (not blog)
NEWSSTR="%%%BLOOOOG%%%"
# page used as blog, usr the source directory as root "/"
NEWSPAGE="/index.md"
# Directory containing pages used as blog.
# set '/' for whole site
# All other pages on the website won't be in your feed
BLOGDIR="/"
## ATOM
AUTHOR="batman"
EMAIL="batmant@foo.org"
# only for atom feed. Must be YYYY-MM-DD
FIRST_CREATION="2018-05-20"
#!/bin/sh
setdirs() {
# Set input dir and output dir according to $1
IDIR="$(echo ${1} | sed -e 's,/*$,,')"
if [ -z "${IDIR}" ] || [ ! -d ${IDIR} ]; then
echo "swx - version ${VERSION}"
echo "Usage: swx [dir]"
exit 1
fi
ODIR="$PWD/$(basename ${IDIR}).static"
}
domenulist() {
# Create a html unordered list of files present in the directory
# to make an index of the page
# $BL files are ignored
echo "<ul>"
for f in $(ls $(dirname "${1}")/) ; do
sw_filter $i && continue
[ -n "$(echo $f | grep 'index.$EXT$')" ] && continue
echo "<li><a href=\"$(echo $f | sed -e "s,$EXT$,.html,g") \">$(echo $f | sed -e 's/\..*$//' -e 's/[_-]/ /g')</a></li>"
done
echo "</ul>"
}
sw_filter() {
# return 0 if file in blacklist
for b in ${BL}; do
[ "$b" = "$1" ] && return 0
done
}
sw_main() {
# Create the main part of html page
# if the file is empty, we insert an index of files in the directory
if [ -z $(uname |grep "BSD") ]; then
if [ $(stat "${1}" -c %s) -eq 0 ]; then
domenulist "${1}"
else
${CONVERTER} "${1}"
fi
else
if [ $(stat -f %z "${1}") -eq 0 ]; then
domenulist "$1"
else
${CONVERTER} "${1}"
fi
fi
}
sw_navpath() {
# echo where the user is with links
# sed replace spaces with _
DIRNAME="$(dirname "${1}" | sed -e 's/ /_/g' )"
RELPATH="."
NAVPATH=""
while [ "${DIRNAME}" != "${IDIR}" ]; do
NAVPATH="<a href=\"${RELPATH}\">$(basename "${DIRNAME}")</a>/${NAVPATH}"
DIRNAME=$(dirname "${DIRNAME}")
RELPATH="../${RELPATH}"
done
echo "${NAVPATH}"
}
sw_menu() {
### add list of files present in the directory, without backlisted $BL
echo "<div id='navlist'>"
# page list in this dir, rpelaces with .html extension
FILES=$(ls $(dirname ${1}) | sed -e "s,$EXT$,.html,g")
# Fie name without extension and with space
INAME=$(basename "$(echo ${1} | sed -e 's/\..*$//' -e 's/[_-]/ /g')")
for i in ${FILES} ; do
sw_filter $i && continue # don't add in menu
NAME=$(echo $i | sed -e 's/\..*$//' -e 's/[_-]/ /g') # restore spaces in name
[ -n "$(echo $i | grep 'index.html$')" ] && continue
if [ -z "$(echo $i | grep '\.')" ]; then # no extension its a dir
echo "<a $( [ "$INAME" = "$NAME" ] && echo "class=\"thisPage\" ") href=\"$i\">$NAME/</a>"
else
if [ -n "$(echo $i | grep "\.html")" ]; then # html file
echo "<a $( [ "$INAME" = "$NAME" ] && echo "class=\"thisPage\" ") href=\"$i\">$NAME</a>"
else
echo "<a $( [ "$INAME" = "$NAME" ] && echo "class=\"thisPage\" ") href=\"$i\">$i</a>"
fi
fi
done
echo "</div>"
}
sw_page() {
PAGENAME=$(basename "${1}" |sed -e 's/\..*$//' -e 's/[_-]/ /g')
DIRNAME=$(basename "$(dirname "${1}" |sed -e 's/[_-]/ /g')")
_PAGETITLE_="<title>${TITLE} | ${DIRNAME} - ${PAGENAME}</title>" \
_HEADER_="
<h1 class='headerTitle'><a href='/'>${TITLE}</a></h1>
<div class='headerSubtitle'><a href='/'>${SUBTITLE}</a></div>
"\
_MENU_=$(sw_menu "${1}") \
_NAVPATH_=$(sw_navpath "${1}")\
_MAIN_=$(sw_main "${1}") \
_GENDATE_=$(date +'%d/%m/%Y -- %H:%M') \
envsubst < swx.template
}
generate() {
echo "> Prepare output directory"
# Setup output dir structure
mkdir -p "$ODIR"
# Parse files
echo "> Generating html pages and copying files"
(
if [ -f "${ODIR}/.swx.last" ]; then
# we check the date of last access of files compared to the witness file
find "$IDIR" -newer "${ODIR}/.swx.last" -exec printf '%s\n' '{}' +
else
find "$IDIR" -exec printf '%s\n' '{}' +
fi
) | while read a; do
# file to convert
echo "${a}"
FILEEXT=${a##*.}
if [ ".$FILEEXT" = "$EXT" ]; then
b="$(echo "${a%.*}.html" | sed "s;$IDIR;$ODIR;g")"
else
b="$(echo "${a}" | sed "s;$IDIR;$ODIR;g")"
fi
if [ ".$FILEEXT" = "$EXT" ]; then
sw_page "${a}" > "${b}"
elif [ -d "${a}" ]; then
mkdir -p "${b}"
else
cp "${a}" "${b}"
fi
done
echo "\n\n> Done! :)"
# It's the time of creation of the file that wil be relevant
date > "${ODIR}/.swx.last"
}
<!doctype html>
<html lang="fr">
<head>
${_PAGETITLE_}
<link rel="icon" href="/favicon.png" type="image/png">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<link rel="stylesheet" type="text/css" href="/style.min.css">
<link href="/feed.atom" type="application/atom+xml" rel="alternate" title="Atom feed " />
</head>
<body>
<a id="topOfPage"></a>
<header>
${_HEADER_}
<nav id="menubar">
${_NAVPATH_}
</summary>
${_MENU_}
</nav>
</header>
<main>
<div id="article">
${_MAIN_}
</div>
</main>
<footer>
Le
${_GENDATE_}
avec <a href="https://3hg.fr/Scripts/swx">swx</a>
</footer>
</body>
</html>
#!/bin/sh
# Generate an atom feed
# usage : swx_atom SRCDIR > atom.xml
# Remember to add a link in your html template such as :
# <link href="feed.atom" type="application/atom+xml" rel="alternate" title="Sitewide Atom feed" />
# Load config file
if [ ! -f $PWD/swx.conf ]; then
echo "Cannot find swx.conf in current directory"
exit 1
fi
. $PWD/swx.conf
if [ $# -ne 1 ]; then
echo "usage $0 <dir> > atom.xml"
exit
fi
cat <<EOF
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>${TITLE}</title>
<subtitle>${SUBTITLE}</subtitle>
<link href="${PROTOCOL}${HOSTNAME}"/>
<updated>$(date -u +%Y-%m-%dT%TZ)</updated>
<author>
<name>${AUTHOR}</name>
<email>${EMAIL}</email>
</author>
<id>tag:${HOSTNAME},${FIRST_CREATION}:changes</id>
<link href="${PROTOCOL}${HOSTNAME}/feed.atom" rel="self" type="application/atom+xml" />
<link href="${PROTOCOL}${HOSTNAME}" rel="alternate" type="text/html" />
EOF
BLOGDIR=$(echo "${1}/${BLOGDIR}" | tr -s '//' ) # remove double // in path
# find most recents files on linux or BSD
if [ -z $(uname |grep "BSD") ]; then
RECENTS=$(find "${1}" -type f -name "*${EXT}" -print0 | xargs -0 stat --format '%Y :%y %n' | sort -nr | cut -d: -f2- | grep -E "^${BLOGDIR}" | head -n "${MAX}")
else
RECENTS=$(find "${1}" -type f -name "*${EXT}" -exec stat -f "%m %N" {} \; | sort -nr | cut -d' ' -f2- | grep -E "^${BLOGDIR}" | head -n "${MAX}" )
fi
for i in ${RECENTS}; do
URL=$(echo "${i}" | sed -e "s;${1};${PROTOCOL}${HOSTNAME}/;" -e "s;${EXT};.html;")
PAGETITLE=$(grep -v "^$" "${i}" |sed -n "1p" | sed -e "s;^#;;" -e "s/^[[:space:]+]//")
if [ -z "${PAGETITLE}" ]; then
# don't include empty files
continue
#PAGETITLE="$(echo $(basename ${i}) | sed -e "s;$EXT;;")"
fi
if [ -z $(uname |grep "BSD") ]; then
STAT=$(stat -f %w "${i}")
UPDATED="$(date -ud @${STAT} +%Y-%m-%dT%TZ)"
CREATION_DATE=$(date -ud @${STAT} +%Y-%m-%d)
# If you wan't to have reald updated time, use this :
#UPDATED="$(date -ud @`stat -t ${i}|cut -f13 -d\ ` +%Y-%m-%dT%TZ)"
#CREATION_DATE=$(date -ud @$(stat -f %w "${i}") +%Y-%m-%d)
else
STAT=$(stat -f %m "${i}")
UPDATED=$(date -ur ${STAT} +%Y-%m-%dT%TZ)
CREATION_DATE=$(date -ur ${STAT} +%Y-%m-%d)
# If you wan't to have real updated time, use this :
#UPDATED=$(date -ur $(stat -f %m "${i}") +%Y-%m-%dT%TZ)
#CREATION_DATE=$(date -ur $(stat -f %c "${i}") +%Y-%m-%d)
fi
CONTENT=$(${CONVERTER} ${i})
FILENAME=$(basename ${i} | sed -e "s;$EXT;;")
cat <<EOF
<entry>
<id>tag:${HOSTNAME},$CREATION_DATE:${FILENAME}</id>
<title>${PAGETITLE}</title>
<updated>${UPDATED}</updated>
<link href="${URL}"/>
<content type="html">
<![CDATA[${CONTENT}]]>
</content>
</entry>
EOF
done
echo "</feed>"
#!/bin/sh
# Generate a blog page with recent articles
#
# usage : swx_blog page.html
# if ":::BLOG:::" is found in page.html, it will be replaced by recent articles
# usage : swx_blog src_dir
# if ":::BLOG:::" ($NEWSSTR) is found in $NEWSPAGE, it will be replaced by recent articles
# change it in swx.conf
# Load config file
if [ ! -f $PWD/swx.conf ]; then
echo "Cannot find swx.conf in current directory"
exit 1
fi
. $PWD/swx.conf
if [ ! -f "$LOG" ]; then
echo "Can't find the News file"
exit 1
if [ $# -ne 1 ]; then
echo "usage $0 <dir>"
exit
fi
if [ -z "$1" ]; then
"usage : $0 page.html"
exit 1
fi
. $PWD/swx.conf
. $PWD/swx.functions
WORKTMP=$(mktemp)
# keep MAX news
uniq -u "$LOG" | tail -n $MAX > "$WORKTMP"
mv "$WORKTMP" "$LOG"
setdirs "${1}"
# new entry first
tac "$LOG" > $WORKTMP
WORKTMP=$(mktemp)
NEWS=""
while read line; do
NEWTITLE="$(basename $line | sed -e "s,$EXT$,,g")"
if [ "$NEWTITLE" = "index" ]; then
NEWTITLE="$(basename $(dirname $line))"
fi
URL="$(echo $line | cut -d'/' -f2- | sed -e "s,$EXT$,.html,g")"
PUBDATE="$(stat -c %z "$line")"
if [ "$line" = "$NEWSSTR" ]; then
if [ -z $(uname |grep "BSD") ]; then
RECENTS=$(find "${IDIR}" -type f -name "*${EXT}" -print0 | xargs -0 stat --format '%Y :%y %n' | sort -nr | cut -d: -f2- | head -n "${MAX}")
else
RECENTS=$(find "${IDIR}" -type f -name "*${EXT}" -exec stat -f "%m %N" {} \; | sort -nr | head -n "${MAX}" | cut -d' ' -f2-)
fi
NEWS="\n$NEWS <div class='article'>\n"
NEWS="$NEWS\n <a href="$URL">$NEWTITLE - $PUBDATE </a>"
NEWS="$NEWS\n $($CONVERTER $line) "
NEWS="$NEWS </div>"
done < $WORKTMP
echo "<div class=\"news\">"
echo "" > $WORKTMP
for i in ${RECENTS}; do
NEWTITLE=$(grep -v "^$" "${i}" |sed -n "1p" | sed -e 's/^#//' -e 's/^[[:space:]+]//' )
if [ -z "${NEWTITLE}" ]; then
NEWTITLE="$(basename ${i} | sed -e "s,$EXT$,,g")"
fi
if [ "$NEWTITLE" = "index" ]; then
NEWTITLE="$(basename $(dirname ${i}))"
fi
URL="$(echo ${i} | sed -e "s;${IDIR};;" -e "s,${EXT}$,.html,g")"
#if [ -z $(uname |grep "BSD") ]; then
# PUBDATE="$(date -d @$(stat -c %z "$i") +%d/%m/%Y-%H:%M)"
#else
# PUBDATE="$(date -r $(stat -f %c "$i") +%d/%m/%Y-%H:%M)"
#fi
while read line; do
if [ "$line" != "$NEWSSTR" ]; then
echo "$line" >> $WORKTMP
else
echo "$NEWS" >> $WORKTMP
fi
done < "$1"
mv $WORKTMP "$1"
echo "<div class=\"clear news_link\">"
echo "<a href=\"${URL}\"><span class=\"news_title\">$NEWTITLE</span></a>"
echo "</div>"
done
echo "</div>"
else
echo "$line"
fi
done < "${IDIR}/${NEWSPAGE}" >> "${WORKTMP}"
# Path to page to convert
INPAGE="${IDIR}/${NEWSPAGE}"
# PAth to output file, replace extension with .html
OUTPAGE=$(echo ${ODIR}/${NEWSPAGE} | sed "s;${EXT};.html;")
# Necessary to have the correct menu entries
mv "${WORKTMP}" "${INPAGE}.blog"
BL="${BL} $(echo ${NEWSPAGE}.blog | sed -e 's;^/;;')"
sw_page "${INPAGE}.blog" > "${OUTPAGE}"
# Restore original file
rm "${INPAGE}.blog"
exit 0
#!/bin/sh
IDIR="$(echo $1 | sed -e 's,/*$,,')"
if [ -z "$IDIR" ] || [ ! -d $IDIR ]; then
echo "swx - version $VERSION"
echo "Usage: $0 [dir]"
exit 1
fi
. $PWD/swx.conf
# Setup output dir structure
CDIR=$PWD
ODIR="$CDIR/$(basename $IDIR).gopher"
mkdir -p $ODIR
cp -uv $IDIR/* $ODIR/
find $ODIR -iname "*$EXT" -exec txt2tags -t txt '{}' \;
find $ODIR -iname "*$EXT" -exec rm '{}' \;
figlet "$TITLE" > "$ODIR"/gophermap
echo "\n*" >> "$ODIR"/gophermap
exit 0
......@@ -2,18 +2,18 @@
# Generate html giving the list of pages in a website
# usage : $0 [directory of site] > website_plan.html
DIR="$1"
DIR="${1}"
parse_dir() {
LIST=$(ls $1)
for i in $LIST; do
if [ -d "$1/$i" ] && [ -f "$1/$i/index.html" ]; then
echo "<li><a href=\"$(echo "$1/$i" |sed -e "s,$DIR,,g")/index.html\">$i</a></li>"
LIST=$(ls "${1}")
for i in ${LIST}; do
if [ -d "${1}/${i}" ] && [ -f "${1}/${i}/index.html" ]; then
echo "<li><a href=\"$(echo "${1}/${i}" |sed -e "s,${DIR},,g")/index.html\">${i}</a></li>"
echo "<ul>"
parse_dir "$1/$i"
parse_dir "${1}/${i}"
echo "</ul>"