Name: | albumGenerate |
Typ: | bash |
benötigt: | diverse jquery-Geschichten, convert,exiftool,jhead |
Aus einem Verzeichnis heraus aufgerufen, generiert es aus allen Ordnern in diesem Verzeichnis und den darin enthaltenen Medien-Dateien ein Album im HTML-Format.
Hier ein kurzes Beispiel einer Anwendung.
Ein Bug / ein Feature fiel noch auf. Die Bestellübersicht (s.u.) bietet nicht die Photo-Album Funktionalität.
Details: Das entstehende Album
wird mittels jQuery und lightbox realisiert, es handelt sich um eine reine HTML/JavaScript Geschichte,
eine serverseitige Sprache wird nach der Fertigstellung nicht mehr benötigt.
Um die Dateigrößen und damit die Ladezeichen für den Betrachter
möglichst gering zu halten, werden alle Bild-Dateien mittels des Befehls convert (aus imagemagick)
skaliert. Es existieren also nach dem Durchlauf des Scriptes die Original-Dateien, die Bilddateien welche
vom Benutzer betrachtet werden können und die Thumbnails der diversen Übersichtsseiten.
Neben dem Betrachten der Gallerie ist es möglich, mit dem Programm eine Liste von Bildern zusammen zu stellen. Diese wird angzeigt und kann in Textform ausgegeben werden. Ich nutze dies um die Photos heraus zu suchen, von denen ich Abzüge machen möchte.
Einige Worte zur Anleitung.
Annahme: Wir haben die folgende Ordnerstruktur:
Bilder |_ 2010 | |_ 01JanuarSchnee | |_ 04Ostern | |_ 07Urlaub | |_ 2009 | |_ ... | |_ 2008 |_ ...
Das Script ruft man nun aus den Ordnern 2010 ... 2008 heraus auf. Prinzipiell sollte es auch aus dem Ordner Bilder heraus funktionieren, aber da für ein "Toplevel-Verzeichnis" eine index.html erzeugt wird, welche alle Daten aus den Unterverzeichnissen enthät wähle ich jeweils ein Jahr. Dies ist für meine Zwecke die richtige Größe.
In diese Ordner müssen dann noch manuell einige Verzeichnisse kopiert werden:
Verzeichnis
Verzeichis
Es handelt sich dabei fast ausschließlich um jquery Sources/CSS und benötigte Bilder. Ein paar css werden erzeugt, ein Bild wird als Thumbnail für eine Filmdatei zusätzlich benötigt.
Die benötigten Verzeichnisse und Dateien liegen dem Download bei.
Will man dies nicht, so muss man sich die erzeugten Dateien in ein anderes Verzeichnis kopieren. Dies kann man mit ein paar Shell-Befehlen relativ schnell erledigen. Hier das Prinzip:construct object
mkdir ../../../Album/2010-04-BeispielAlbumGenerate cp -a css/ images/ sources/ index.html ../../../Album/2010-04-BeispielAlbumGenerate find . -type d -name thumbs -exec cp -a --parents {} ../../../Album/2010-04-BeispielAlbumGenerate/ \; find . -type d -name smaller -exec cp -a --parents {} ../../../Album/2010-04-BeispielAlbumGenerate/ \;
Der Quelltext ist dann doch ein Monstrum geworden ... unten ein Link zum Download
#!/bin/bash #bugs, seltsamkeiten, die ich aktuell sehe und nicht reparieren moechte #verzeichnis css und js muss haendig in das aktuelle Verzeichnis koppiert werden #verzeichnisse die vom script verwendet werden sollten keine Bilder enthalten # //0 darf auch kein Verzeichnis heissen #Bei zu vielen Verzeichnissen wird es langsam, liegt an der Bestell-Aufnahme (glaube ich :-) #nehme das daher raus cssDir=css # for css style-file, not as dir of photos sourceDir=sources # for the jquery sources, -"- jquery=jquery-1.4.2.min.js # jquery lib jqueryLightBox=jquery.lightbox-0.5.min.js # jquery Light Box, photos jqueryTree=jquery.treeview.min.js # tree navigation jqueryCookie=jquery.cookie.js # weiss nicht ob noetig :-) jqueryLightBoxCSS=jquery.lightbox-0.5.css styleFile="albumStyle.css" albumTmpList="albumTmpList" movieTypes=( avi mpg mpeg mts mp4 ) #movies als normaler link imageTypes=( jpg jpeg png ) #unterverzeichnisse und prefix fuer thumbs und smaller images thPrefix="thumb_" smPrefix="smaller_" thDir="thumbs" smDir="smaller" #----------------------------------------- #groessen fuer die thumbs, smaller thumbDivWidth=220px thumbHeight=120 # hier ohne px -> fuer convert smallerHeight=500 #functions #-------------------------------------- #die CSS function generateStyles() { bestell=$1 mkdir -p $cssDir cat << endStyle > $cssDir/$styleFile body { background-color: #697ed1; color : #faebd7; } a:link { color:#200096; text-decoration:underline; font-style:italic; } a:visited { color:#200096; text-decoration:underline; font-style:normal; } a:active { color:#200096; text-decoration:none; } h1 { color:#ff0000;} .goon { color: #960096; background-color: #798ee1; } .treeview , .treeview ul { margin-left : 6px; padding-left : 6px; list-style : none; } .treeview li { margin-bottom : 2px ; cursor : pointer; } .folder:hover { background-color : #798ee1; } #divButtonNavigation{ background-color : #697ee1; color : #faebd7; position : fixed; top : 0px; left : 0px; border-right : 6px groove #697ee1; border-bottom : 6px groove #697ee1; z-index : 10; padding : 3px; cursor : pointer; display : none; } #divButtonNavigationHide{ background-color : #697ee1; color : #faebd7; border-left : 6px groove #697ee1; border-right : 6px groove #697ee1; border-bottom : 6px groove #697ee1; position : fixed; top : 0px; left : 100px; z-index : 10; display : block; padding : 3px; cursor : pointer; } #divButtonBestellAuswahl { background-color : #697ee1; color : #faebd7; border-left : 6px groove #697ee1; border-right : 6px groove #697ee1; border-bottom : 6px groove #697ee1; position : fixed; top : 0px; right : 30px; z-index : 10; display : none; padding : 3px; cursor : pointer; width : 200px; text-align : center; } #divBestellung { background-color : #697ee1; color : #faebd7; border-left : 1px solid #ddd; border-right : 1px solid #ddd; border-bottom : 1px solid #ddd; position : fixed; top : 0px; right : 270px; display : inline-block; z-index : 10; padding : 3px; cursor : pointer; } /* gebe diesen das Aussehen von Buttons */ #divButtonNavigation, #divButtonNavigationHide, #divButtonBestellAuswahl, #divButtonBestellListe, #divButtonBestellUebersicht { display : inline-block; background-color : #bbb; color : #00A; padding : 2px; border : 3px outset #AAA; } #divButtonNavigation {display:none;}/*wieder ausblenden*/ #divButtonNavigation:hover, #divButtonNavigationHide:hover, #divButtonBestellAuswahl:hover, #divButtonBestellListe:hover, #divButtonBestellUebersicht:hover { background-color : #CCC; color : #00F; border : 3px inset #AAA; } #divNavigation { background-color : #697ee1; color : #faebd7; position : absolute; top : 0px; bottom : 0px; /* immer volle Hoehe */ left : 0px; padding-top : 50px; padding-right : 20px; min-width : 200px; display : block; z-index : 5; cursor : text; position : fixed; overflow : auto; } #gallery { margin-top : 50px; margin-left : 100px; width : 95%; margin-left : auto; margin-right : auto; border : 1px solid #aaa; /* background-color : blue; */ } #gallery img { margin : 10px; border : 5px solid #3e3e3e; border-width : 5px 5px 10px; } #gallery a:hover img { border : 5px solid #fff; border-width : 5px 5px 10px; color : #fff; } #gallery a:hover { color: #fff; } .h { display : none; } .fileEntry { /* color : yellow; */ display : inline-block; width : $thumbDivWidth; /* border : 1px solid; */ text-align : center; } div.fileEntry > div { /* erster div mit dem Filenamen */ font-family : sans-serif; font-size : x-small; padding : 0px 5px; /* oben unten 2. rechts links */ border : 0px solid; position : relative; top : -5px; } .bestellung { font-family : sans-serif; font-size : x-small; text-align : center; } .bestellung input { font-size : xx-small; text-align : right; } endStyle if [[ $bestell. != 'j.' ]] then cat << endStyle >> $cssDir/$styleFile /* variante ohne Bestellung, einfach ausblenden :-) */ #divBestellung, #divButtonBestellAuswahl, #divButtonBestellListe, #divButtonBestellUebersicht { display : none; } endStyle fi } #-------------------------------------------------- #write the main header to index.html function generateIndexHead() { bestell=$1 rausA=rausE="" # leer, wird unten ggf. gesetzt echo "Generate Header of index.html in main directory" cat << endIndex > index.html <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta name="author" content="albumGenerate.sh by kr"> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" type="text/css" href="$cssDir/$styleFile"> <link rel="stylesheet" type="text/css" href="$cssDir/$jqueryLightBoxCSS"> <script type="text/javascript" src="$sourceDir/$jquery" > </script> <script type="text/javascript" src="$sourceDir/$jqueryLightBox" ></script> <script type="text/javascript" src="$sourceDir/$jqueryTree"> </script> endIndex if [[ $bestell. != 'j.' ]] then cat << endIndex >> index.html <!-- Bestellmoeglichkeit wurde ausgeschaltet, daher in diesem Java-Script einiges Nutzlos beziehungsweise auskommentiert --> endIndex rausA="/* (keine Bestellmoeglichkeit) " rausE=" (Ende keine Bestellmoeglichkeit) */" fi cat << endIndex >> index.html <script type="text/javascript"> //globals //array, one entry for each directory, containing object of type fileEntry var allDirectories=new Array(); var actualKey="-1"; //-1: nicht gegeben, "0": wir sind auf der Uebersicht var showBestellAufnahme = false; var bestellteFiles = new Array(); $rausA function pruefeBestellteFiles(fEntry ) { var found = false; var i,index = 0; //for each ( var entry in bestellteFiles) //Mist for each erst ab js1.7, IE 8 nicht, hier brauche ich //es eigentlich nicht for (i = 0; i < bestellteFiles.length; ++i) { if (bestellteFiles[i] == fEntry) { found = true; break; } } index = i; if (!found && fEntry.bestellungen != "0") { bestellteFiles.push(fEntry); //anfuegen } else if (found && fEntry.bestellungen == 0) { bestellteFiles.splice(index,1); //eines loeschen //klappt auch aus der Mitte heraus, es wird neu //nummeriert - scheint so } } $rausE \$(document).ready(function(){ //navigation als tree \$("#navigationTree").treeview({ persist: "location", collapsed: true, unique: false }); /* \$("#divButtonNavigation").mouseenter( function () */ \$("#divButtonNavigation").click( function () { \$(this).hide(); \$("#divNavigation").slideDown("slow"); \$("#divButtonNavigationHide").slideDown("slow"); //get width of navigation var breite = \$("#divNavigation").width(); breite+=20; breite+="px"; //alert (breite); \$("#gallery").css("margin-left",breite); //galerie nach rechts }); /* \$("#divButtonNavigationHide").mouseenter(function()*/ \$("#divButtonNavigationHide").click(function() { \$("#divNavigation").slideUp("slow"); \$("#divButtonNavigation").slideDown("slow"); \$(this).hide() \$("#gallery").css("margin-left","auto"); //schiebt die Galerie wieder nach links }); /* \$("#divButtonBestellAuswahl").mouseenter( function()*/ $rausA \$("#divButtonBestellAuswahl").click( function() { if (!showBestellAufnahme) { \$(".fileEntry .bestellung").slideDown("slow"); \$(this).html("Bestellauswahl ausblenden"); } else { \$(".fileEntry .bestellung").slideUp("slow"); \$(this).html("Bestellauswahl einblenden"); } showBestellAufnahme = ! showBestellAufnahme; }); $rausE \$(".folder").click( function(){ var key=\$(this).find("span")[0];//first element of array key=\$(key).text(); //und text heraus holen //fill the content-Div //\$("#gallery").text(key); geht prinzipiell //check actual key $rausA if (actualKey != "-1" ) { var actualDir = bestellteFiles; if (actualKey != "0") //komme aus einem anderen Folder actualDir = allDirectories[actualKey]; //get the contents of all input fields allInputs=\$("#gallery input"); //klappt //\$("#gallery input").css("border", "2px dotted blue") //alert (allInputs.length); for (i = 0; (i < allInputs.length) && (i < actualDir.length ) ; ++i) { actualDir[i].bestellungen = allInputs[i].value; //sichern, reihenfolge müsste stimmen pruefeBestellteFiles(actualDir[i]); } } actualKey=key; $rausE var anzahl = allDirectories[key].length; //alert (anzahl); content=""; //-> should be the way for ( i = 0; i < anzahl; ++i) { content+=allDirectories[key][i].ToHTML(); } \$("#gallery").html(content);//set all if (anzahl > 0) //sonst folder ohne Bild-Dateien { \$('#gallery a.typeImage').lightBox(); // Select all links in object with gallery ID //which are of class typeImage } $rausA if (showBestellAufnahme) { \$(".fileEntry .bestellung").slideDown("slow"); \$("#divButtonBestellAuswahl").html("Bestellauswahl ausblenden"); } $rausE }); $rausA \$(".fileEntry .up").live("click",function() //for all future elements -> Event einhaengen { var el=\$(this).siblings()[0]; el.value = parseInt(el.value) + 1; }); \$(".fileEntry .down").live("click",function() //for all future elements -> Event einhaengen { var el=\$(this).siblings()[1]; if (parseInt(el.value) > 0) el.value = parseInt(el.value) - 1; }); //buttons liste und übersicht \$("#divButtonBestellListe").click( function() { if (actualKey != "-1") { var actualDir = bestellteFiles; if (actualKey != "0") //komme aus einem anderen Folder actualDir = allDirectories[actualKey]; //get the contents of all input fields allInputs=\$("#gallery input"); //klappt for (i = 0; (i < allInputs.length) && (i < actualDir.length ) ; ++i) { actualDir[i].bestellungen = allInputs[i].value; //sichern, reihenfolge müsste stimmen if (actualKey != 0) pruefeBestellteFiles(actualDir[i]); } } actualKey = "-1"; var bestellFenster = window.open(); var datum = new Date(); bestellFenster.document.write("<html><head><title>Bestellliste</title></head><body>\n"); bestellFenster.document.write("<hr>\n"); bestellFenster.document.write("Bestellung: " + datum + "<br>\n"); bestellFenster.document.write(" bitte an mich, z.B. copy & paste und mail :-) <br>\n"); bestellFenster.document.write("<hr>\n"); //for each (var fEntry in bestellteFiles ) erst ab js 1.7 for ( var i = 0; i < bestellteFiles.length; ++i) { bestellFenster.document.write(bestellteFiles[i].getFullName()); bestellFenster.document.write(" " + bestellteFiles[i].bestellungen + "</br>\n"); //bestellFenster.document.write(fEntry.getFullName()); //bestellFenster.document.write(" " + fEntry.bestellungen + "</br>\n"); } bestellFenster.document.write("</body></html>"); bestellFenster.document.close(); //alert("Liste"); //alert("Liste"); }); //end of bestellListe click //------------------------------------------------------------------------------- \$("#divButtonBestellUebersicht").click( function () { if (actualKey != "-1" ) { //noch aktualisieren allInputs=\$("#gallery input"); //get the contents of all input fields var actualDir = bestellteFiles; if (actualKey != "0") //komme aus einem anderen Folder actualDir = allDirectories[actualKey]; for (i = 0; (i < allInputs.length) && (i < actualDir.length ) ; ++i) { actualDir[i].bestellungen = allInputs[i].value; //sichern, reihenfolge müsste stimmen pruefeBestellteFiles(actualDir[i]); } } actualKey = "0"; var content=""; var anzahl = bestellteFiles.length; //for each (var fEntry in bestellteFiles) for (var i = 0; i < anzahl; ++i) { content+= bestellteFiles[i].ToHTML(); } \$("#gallery").html(content);//set all if (showBestellAufnahme) { \$(".fileEntry .bestellung").slideDown("slow"); \$("#divButtonBestellAuswahl").html("Bestellauswahl ausblenden"); } }); //end of bestellUebersicht click \$("#divButtonBestellAuswahl").slideDown("slow"); $rausE //zum Schluss noch die Breite der gallerie anpassen var breite = \$("#divNavigation").width(); breite+=20; breite+="px"; //alert (breite); \$("#gallery").css("margin-left",breite); //galerie nach rechts }); //end of $.ready </script> endIndex } #---------------------------------------------------------- #remove all directories which does not contain #files of allowed type function removeEmptyDirs() { dirCount=${#allDirectories[@]} declare -a markedForRemoval for (( i = 0 ; i < $dirCount ; i++ )) # loop over all directories do if [[ -e $albumTmpList ]] then rm -f $albumTmpList fi actualDir=${allDirectories[$i]} for type in ${imageTypes[*]} do find "$actualDir" -maxdepth 1 -type f -iname "*$type" | sort >> $albumTmpList #find all files in this dir, filename must match the type, caseinsesitive done for type in ${movieTypes[*]} do find "$actualDir" -maxdepth 1 -type f -iname "*$type" | sort >> $albumTmpList #find all files in this dir, filename must match the type, case insesitive done # read this file-names and strip the path j=0 files=( ) # empty array while read file do file=${file##*/} files[$j]=$file let j++ done < $albumTmpList #following check is complicated but should work. #I have not build up a tree structure, so I check if there #are accepted files below this dir. #if not this dir is a leaf dir or would become a leaf dir after removing #the dirs inside if [[ ${#files[@]} -eq 0 ]] #nothing found, check if dir is a tree leaf -> then remove then fileCount=0 for type in ${imageTypes[*]} do tmpCounter=$(find "$actualDir" -type f -iname "*$type" | wc -l) let fileCount+=tmpCounter done for type in ${movieTypes[*]} do tmpCounter=$(find "$actualDir" -type f -iname "*$type" | wc -l) let fileCount+=tmpCounter done if [[ $fileCount -eq 0 ]] # found nothing, this dir could be removed in array then markedForRemoval=("${markedForRemoval[@]}" "$i" ) #echo "mark $actualDir" fi fi #check on leaf dir finished ------------------------------------------ done #end of for loop throug all directories #remove directories whith no files of accepted types for removeIt in "${markedForRemoval[@]}" do echo "We kick: " "${allDirectories[$removeIt]}" unset allDirectories[$removeIt] done allDirectories=("${allDirectories[@]}") # und array "eindampfen" } #----------------------------------------------------------------- #read all directories and build global dirList #build 2 dimensional associative array with the content #of the directories - in javascript -> add to header #dont use dir $thDir and $smDir (thumbs and smaller) function readDirectories { local i=0 find . -type d | sort > $albumTmpList while read dir do lastPart=${dir##*/} #images beinhaltet lightbox-bilder if [[ $lastPart != $thDir && $lastPart != $smDir && $dir != "./images" ]] then allDirectories[$i]=$dir let i++ else echo "Skip $dir it is a dir with thumbs or smaller images" fi done < $albumTmpList #remove top level dir unset allDirectories[0] allDirectories=("${allDirectories[@]}") # mit " erhält man auch leerzeichen in einem Array-Eintrag #for-loop -> auch mit Anfuehrungszeichen #remove empty dirs removeEmptyDirs #extend the header of the index.html - file cat << endObjectDefinition >> index.html <script type="text/javascript"> //object for one file-Entry function fileEntry(name,dir, type) { //public attributes this.name = name; this.dir = dir; this.type = type; //type is image or movie this.bestellungen = 0; //private attributes var fullName = this.dir + "/" + this.name; //double / doesn't matter var thumbName = this.dir + "/$thDir/$thPrefix"+this.name; var smallerName = this.dir + "/$smDir/$smPrefix"+this.name; //get html-Representation of element this.ToHTML = function () //public method of object fileEntry { var erg = "<div class='fileEntry'>\n"; if (type=="movie") { erg += " <a class='typeMovie' href=\"" + fullName + "\">"; //private - ohne this. erg += " <img class=\"thumb\" width='150px' src='images/filmrolle.gif' alt=\"" + this.name + "\"></a>\n"; erg += " <div>" + this.name + "</div>\n"; //hier keine Bestellung erg += " <div style='display:none' class='bestellung' >\n" + " Film, keine Bestellung </div>"; } else if (type=="image") { erg += " <a class='typeImage' href=\"" + smallerName + "\">"; //private - ohne this. erg += " <img class=\"thumb\" src=\"" + thumbName + "\" alt=\"" + this.name + "\"></a>\n"; erg += " <div>" + this.name + "</div>\n"; erg += " <div style='display:none' class='bestellung' >\n" + " <span class='up' style='cursor: pointer; border:solid 1px;'> ∧ </span>\n" + " <input class='inputBestellung' type='text' size='2' value='" + this.bestellungen +"' maxlength='2'>\n" + " <span class='down' style='cursor: pointer; border:solid 1px;'> ∨ </span>\n" + " </div>"; } else erg += "something went wrong"; erg += "</div>\n"; return erg; } this.getFullName = function () { var fn = fullName.replace(/\/\//g,"/"); return fn; } } endObjectDefinition #get the files - maybe we could combine this with removeEmptyDirs #but this way should be clearer and cause I mix shell scripting and #javascript - I prefer this way echo "// empty Array possible, should be no problem" >> index.html for actualDir in "${allDirectories[@]}" # " wichtig, falls leerzeichn do echo "allDirectories[\"$actualDir\"]=new Array() " >> index.html #read the imageTypes for type in ${imageTypes[*]} do find "$actualDir" -maxdepth 1 -type f -iname "*$type" | sort > $albumTmpList while read file do file=${file##*/} # name, now generate javascript entry for new file echo "allDirectories[\"$actualDir\"].push(new fileEntry(\"$file\",\"$actualDir\",'image'));" >> index.html done < $albumTmpList done #read the movieTypes for type in ${movieTypes[*]} do find "$actualDir" -maxdepth 1 -type f -iname "*$type" | sort> $albumTmpList while read file do file=${file##*/} # name, now generate javascript entry for new file echo "allDirectories[\"$actualDir\"].push(new fileEntry(\"$file\",\"$actualDir\",'movie'));" >> index.html done < $albumTmpList done done echo "</script>" >> index.html echo "</head>" >> index.html echo "<body>" >> index.html } #---------------------------------------------------------- function generateNavigationTree() { cat << eNavIntro >> index.html <div id="divButtonNavigation"> Navigation<br> </div> <div id="divButtonBestellAuswahl"> Bestellauswahl einblenden </div> <div id="divBestellung"> <div id="divButtonBestellListe"> Bestell-Liste erzeugen </div> <div id="divButtonBestellUebersicht"> Bestell-Übersicht </div> </div> <span id="divButtonNavigationHide"> ausblenden </span> <!-- Liste zur Navigation, gebe den vollen Namen hidden mit, class h --> <div id="divNavigation"> <ul id="navigationTree" class="filetree"> eNavIntro firstEntry=${allDirectories[0]##*/} fullFirst=${allDirectories[0]} indent=" " echo -n "$indent<li> <span class=\"folder\"> $firstEntry <span class="h" >$fullFirst</span></span> " >> index.html prevAnzahl=$(echo ${allDirectories[0]} | sed 's/[^/]//g' | wc -L) # wieviele / -> tiefe dirCount=${#allDirectories[@]} lenIndent=${#indent} for (( i=1; i < $dirCount; i++)) do lenIndent=${#indent} anzahl=$(echo ${allDirectories[$i]} | sed 's/[^/]//g' | wc -L) #ersetze alles ausser / und bestimme die Länge der Zeile #das ist die Anzahl der / in diesem directory #echo $anzahl $prevAnzahl if [ $anzahl -gt $prevAnzahl ] # eine Ebene tiefer, hier nur eine moeglihc then indent="$indent " # haenge 2 an echo '<span class="goon">»</span>' >> index.html #kommen noch unterpunkte echo "$indent<ul>" >> index.html #neue unterliste in diesem listenpunkt indent="$indent " # haenge 2 an elif [ $anzahl -lt $prevAnzahl ] # Ebene hoeher then # Vorsicht, hier muss man ggf. mehrere Ebenen hoch hoeher=$prevAnzahl-$anzahl echo "</li>" >> index.html #erstmal etzten Punkt schließen for (( hZaehler=0 ; hZaehler < $hoeher ; hZaehler++ )) do let lenIndent-=2; indent=${indent:0:$lenIndent} #von 0 bis len #echo "$indent"${#indent} echo "$indent</ul>" >> index.html # unterebene schließen let lenIndent-=2; indent=${indent:0:$lenIndent} #0 bis len echo "$indent</li>" >> index.html done else echo "</li>" >> index.html #listenpunkt schließen fi #folgendes auf jedem Fall, leading path removed aktName=${allDirectories[$i]} aktName=${aktName##*/} echo -n "$indent<li> <span class=\"folder\"> $aktName <span class='h'>${allDirectories[$i]}</span> </span>" >> index.html prevAnzahl=$anzahl done let lenIndent-=2; indent=${indent:0:$lenIndent} echo "$indent</li>" >> index.html let lenIndent-=2; indent=${indent:0:$lenIndent} echo "$indent</ul>" >> index.html #end of List echo "</div>" >> index.html echo "<div id='gallery' > <p style=\"text-align:center;\">Galerie</p> </div>">> index.html; echo "</body>" >> index.html echo "</html>" >> index.html } #---------------------------------------------------------- function convertToThumbsAndSmaller() { rotiere=$1 echo " do the thumbs and smaller images? (only skip if you have them) " echo "s: skip" echo "a: ask for every dir" echo "e: if file exist don't generate again" echo "Enter to generate thumbs and smaller" read doThumbs if [[ $doThumbs. != "s." ]] then for actualDir in "${allDirectories[@]}" # " wichtig, falls leerzeichn do if [[ $doThumbs. == "a." ]] then echo -n "images and thumbs for $actualDir (j/n) [n]: " read imgInDir else imgInDir="j" fi if [[ $imgInDir. == "j." ]] then mkdir -p "$actualDir/$thDir" mkdir -p "$actualDir/$smDir" for type in ${imageTypes[*]} do find "$actualDir" -maxdepth 1 -type f -iname "*$type" | sort > $albumTmpList while read file do newThumb=${file%/*}"/$thDir/$thPrefix"${file##*/} newSmaller=${file%/*}"/$smDir/$smPrefix"${file##*/} #hier test ob file existiert, falls ja wird die konvertierung #nicht durchgefuehrt, wenn der user die Option e gewaehlt hat #pruefe nur newSmaller processFile=1 if [[ -e $newSmaller && "$doThumbs" == "e" ]] then processFile=0 fi if [[ "$processFile" -eq "1" ]] then # ggf test auf notwendigkeit des rotierens orient=1 if [[ $rotiere. != 'n.' ]] then orient=$(exiftool -q -s -s -s -n -Orientation "$file") if [[ $orient -ne 1 ]] then #echo cp $file $file"_backUpBeforeRotation" cp "$file" "$file""_backUpBeforeRotation" jhead -autorot $file fi fi convert -verbose -thumbnail x$thumbHeight "$file" "$newThumb" convert -verbose -resize x$smallerHeight "$file" "$newSmaller" if [[ $orient -ne 1 ]] then mv "$file""_backUpBeforeRotation" "$file" fi else echo "skip $file" fi #ende soll file bearbeitet werden done < $albumTmpList done fi done fi } #---------------------------------------------------------- cat << endIntro Erzeuge ein Album aus allen Verzeichnissen und Unterverzeichnissen Das oberste Verzeichnis spielt eine Sonderrolle. Hier wird eine index.html erzeugt, die die Navigation für die Unterverzeichnisse zur Verfügung stellt. Die Dateien $jquery, $jqueryLightBox und $jqueryTree müssen in das Verzeichnis $sourceDir kopiert werden. Ein Verzeichnis $cssDir und die Datei $cssDir/$styleFile werden angelegt. In $cssDir ist noch die css Datei fuer lightbox notwendig Die Datei $albumTmpList wird erzeugt bzw ueberschrieben. Die Bilder koennen bei Bedarf automatisch gedreht werden, die Originale werden dabei nicht veraendert. Dazu sind die Programme jhead, jpegtran und exiftools noetig und die Kamera muss die exif-Informationen zur Orientierung gespeichert haben. Optionen Ctrl-C -> Abbruch j -> automatisch drehen (Voreinstellung) n -> nicht drehen endIntro read rotiere cat << endBestell Urspruenglich habe ich mal eine Bestellannahme hinzugefuegt, damit man die Files, von denen man einen Abzug machen moechte hier waehlen kann, um eine Liste zu bekommen. Das wird optional gemacht, da das resultierende Javascript bei grossen Hierarchien sonst zu langsam wird. Also - Bestell-Geschichte gewuenscht: n / (j) endBestell read bestell #Html-Datei index.html erzeugen, diese hatte im ersten entwurf einen frame generateStyles $bestell #write style file generateIndexHead $bestell # Kopf schreiben readDirectories #read directory tree, used for navigation div generateNavigationTree #div fuer die Navigation füllen convertToThumbsAndSmaller $rotiere # if the thumbs are available we don't generate them #leere Verzeichnisse entfernen find . -ignore_readdir_race -type d -empty -name smaller -exec rmdir {} \; find . -ignore_readdir_race -type d -empty -name thumbs -exec rmdir {} \; echo "Vergessen Sie nicht die fehlenden Dateien in das css Verzeichnis zu kopieren" echo "Beachten Sie, dass sie auch das Verzeichnis sources im aktuellen Verzeichnis benoetigen"