BEGIN { BOM = "\357\273\277" # ByteOrderMark UTF-16/UTF-32 BOM_DISPLAY = "\\357\\273\\277" CMD_MKDIR = "mkdir" CMD_LINK_OR_COPY = "ln" CMD_SHELL = "/bin/sh" CMD_GREP = "grep" CMD_DOIT = "_doit.sh" if (FILE_PATTERN == "") FILE_PATTERN = "*.jpg" if (MY_FLORA_ID == "") MY_FLORA_ID="83c7eaa3-ba10-5252-aaeb-7033c00bb1ca" if (IN_DIR == "") IN_DIR = "." if (OUT_DIR == "") OUT_DIR = "result" if (system(CMD_MKDIR " " OUT_DIR)) error("Could not create output directory '" OUT_DIR "'.") if (MODIFICATIONS_FILE == "") MODIFICATIONS_FILE = "local/modifications.csv" if (system("test -r " MODIFICATIONS_FILE) != 0) MODIFICATIONS_FILE = "" DATE = "date" SCIENTIFIC_NAME = "scientific name" NAME = "name" NOTES = "notes" TAGS = "tags" UNKNOWN = "N.N." SN_COUNT = 0 headers[1] = "lfd. Nr." headers[2] = "wissenschaftlicher Name" headers[3] = "Name" headers[4] = "Zeitpunkte" headers[5] = "Markierungen" headers[6] = "Notizen" headers_html[1] = "lfd. Nr." headers_html[2] = "wissenschaftlicher Name" headers_html[3] = "Name" headers_html[4] = "Markierungen" headers_html[5] = "Notizen" SEPARATOR_INTEXT_PLAIN = "|" SEPARATOR_INTEXT_CSV = "|" SEPARATOR_INTEXT_HTML = " " SEPARATOR_FIELD_PLAIN = "\t" SEPARATOR_FIELD_CSV = "," SEPARATOR_FIELD_HTML = "" STARTER_FIELD_PLAIN = "" STARTER_FIELD_CSV = "\"" STARTER_FIELD_HTML_HEAD = "" STARTER_FIELD_HTML_DATA = "" FINISHER_FIELD_PLAIN = "" FINISHER_FIELD_CSV = "\"" FINISHER_FIELD_HTML_HEAD = "" FINISHER_FIELD_HTML_DATA = "" SEPARATOR_RECORD_PLAIN = "\n" SEPARATOR_RECORD_CSV = "\n" SEPARATOR_RECORD_HTML = "\n" STARTER_RECORD_PLAIN = "" STARTER_RECORD_CSV = "" STARTER_RECORD_HTML = "" FINISHER_RECORD_PLAIN = "" FINISHER_RECORD_CSV = "" FINISHER_RECORD_HTML = "" SEPARATOR_TABLE_PLAIN = "\n" SEPARATOR_TABLE_CSV = "\n" SEPARATOR_TABLE_HTML = "" STARTER_TABLE_PLAIN = "" STARTER_TABLE_CSV = "" STARTER_TABLE_HTML = "\n" FINISHER_TABLE_PLAIN = "\n" FINISHER_TABLE_CSV = "\n" FINISHER_TABLE_HTML = "\n
\n" map_field_plain["separator"] = SEPARATOR_FIELD_PLAIN map_field_plain["starter"] = STARTER_FIELD_PLAIN map_field_plain["finisher"] = FINISHER_FIELD_PLAIN map_field_csv["separator"] = SEPARATOR_FIELD_CSV map_field_csv["starter"] = STARTER_FIELD_CSV map_field_csv["finisher"] = FINISHER_FIELD_CSV map_field_html_head["separator"] = SEPARATOR_FIELD_HTML map_field_html_head["starter"] = STARTER_FIELD_HTML_HEAD map_field_html_head["finisher"] = FINISHER_FIELD_HTML_HEAD map_field_html_data["separator"] = SEPARATOR_FIELD_HTML map_field_html_data["starter"] = STARTER_FIELD_HTML_DATA map_field_html_data["finisher"] = FINISHER_FIELD_HTML_DATA map_record_plain["separator"] = SEPARATOR_RECORD_PLAIN map_record_plain["starter"] = STARTER_RECORD_PLAIN map_record_plain["finisher"] = FINISHER_RECORD_PLAIN map_record_csv["separator"] = SEPARATOR_RECORD_CSV map_record_csv["starter"] = STARTER_RECORD_CSV map_record_csv["finisher"] = FINISHER_RECORD_CSV map_record_html["separator"] = SEPARATOR_RECORD_HTML map_record_html["starter"] = STARTER_RECORD_HTML map_record_html["finisher"] = FINISHER_RECORD_HTML map_table_plain["separator"] = SEPARATOR_TABLE_PLAIN map_table_plain["starter"] = STARTER_TABLE_PLAIN map_table_plain["finisher"] = FINISHER_TABLE_PLAIN map_table_csv["separator"] = SEPARATOR_TABLE_CSV map_table_csv["starter"] = STARTER_TABLE_CSV map_table_csv["finisher"] = FINISHER_TABLE_CSV map_table_html["separator"] = SEPARATOR_TABLE_HTML map_table_html["starter"] = STARTER_TABLE_HTML map_table_html["finisher"] = FINISHER_TABLE_HTML PAGE_FORMAT_START = "\n" \ "\n" \ "" \ "%s\n\n" PAGE_FORMAT_HEADLINES = "

%s

\n

%s

\n" PAGE_FORMAT_END = "

 

\n\n\n" IMAGE_WIDTH = 236 IMAGE_HEIGHT = 512 } function output(outfile, s) { printf "%s", s >> outfile } function check_BOMid(s) { if (s != BOM "id") { error("Header line does not start with field '" BOM_DISPLAY "id', but with '" s "'.") } } function merge_strings(old, new) { if (new == "") return old if (old == "") return new merged = old split(new, newvalues, SEPARATOR_INTEXT_PLAIN) split(old, oldvalues, SEPARATOR_INTEXT_PLAIN) for (n in newvalues) { nv = newvalues[n] isnew = 1 for (o in oldvalues) if (nv == oldvalues[o]) { isnew = 0 break } if (isnew == 1) merged = merged SEPARATOR_INTEXT_PLAIN nv } delete newvalues delete oldvalues return merged } function field2href(field, target) { if (FORMAT != "HTML") return field if (target == "") target = field "/index.html" return "" field "" } function format_line(outfile, key, value) { if (value != "") output(outfile, "" key ": " value "
\n") } function format_navigation(outfile, array, array2, i) { output(outfile, "\n") } function format_record(outfile, map_field, map_record, fields) { output(outfile, map_record["starter"]) for (i = 1; i in fields; i++) output(outfile, (i == 1 ? "" : map_field["separator"]) \ map_field["starter"] \ (FORMAT == "CSV" ? quote_csv(fields[i]) : fields[i]) \ map_field["finisher"]) output(outfile, map_record["finisher"]) } function format_table(outfile, map_field_head, map_field_data, map_record_head, map_record_data, map_table, headers, master, a1, a2, a3, a4) { output(outfile, map_table["starter"]) format_record(outfile, map_field_head, map_record_head, headers) for (j = 1; j in master; j++) { mstr = master[j] data[1] = j data[2] = field2href(mstr) data[3] = a1[mstr] if (FORMAT == "HTML") { data[4] = a3[mstr] data[5] = a4[mstr] } else { data[4] = a2[mstr] data[5] = a3[mstr] data[6] = a4[mstr] } output(outfile, map_record_data["separator"]) format_record(outfile, map_field_data, map_record_data, data) } output(outfile, map_table["finisher"]) } function create_subdir_cmd(outfile, outdir) { output(outfile, CMD_MKDIR " '" outdir "'\n") } function collect_files_cmd(outfile, dates, pattern, outdir) { n = split(dates, d, "\\" SEPARATOR_INTEXT_PLAIN) for (i = 1; i <= n; i++) { date = d[i] output(outfile, CMD_LINK_OR_COPY " '" IN_DIR "/" date "/'" pattern " '" outdir "'\n") } } function filename2datetime(filename) { # 2025-09-07T12_20_51Z-2.jpg d1 = substr(filename, 1, 10) t1 = substr(filename, 12, 8) gsub("_", ":", t1) return d1 " " t1 } function normalise_datetimes(datetimes) { datecount = split(datetimes, d, SEPARATOR_INTEXT_PLAIN) for (i = 1; i <= datecount; i++) datelist = (i == 1 ? "" : datelist ", ") filename2datetime(d[i]) delete d return datelist } function format_images(outfile, sn, files) { output(outfile, "

\n") for (i = 1; i in files; i++) { fn = files[i] alt = sn " @ " filename2datetime(fn) " GMT" output(outfile, (i == 1 ? "" : "\n") \ "" \ "\""" \ "") } output(outfile, "\n

\n") } function apply_modifications(modfile) { result = getline < modfile if (result < 1) return result for (i = 1; i <= NF; i++) column[$i] = i scientific_name_field = column[SCIENTIFIC_NAME] #date_field = column[DATE] name_field = column[NAME] note_field = column[NOTES] tags_field = column[TAGS] line_count = 1 mod_count = 0 while (getline < modfile > 0) { line_count++ sn = $scientific_name_field #print "line " line_count ", sn = " sn if (sn == "") error("Empty field \"" SCIENTIFIC_NAME \ "\" in file \"" modfile \ "\", line " line_count ".") if (SN_COUNT == 0 || ! (sn in sns)) { sni[++SN_COUNT] = sn sns[sn] = SN_COUNT # debug print "New plant: \"" sn "\", nr. " SN_COUNT \ ", in file \"" modfile \ "\", line " line_count "." } #sn_names[sn] = merge_strings(sn_names[sn], $name_field) sn_names[sn] = $name_field #sn_dates[sn] = merge_strings(sn_dates[sn], $date_field) sn_notes[sn] = $note_field sn_tagss[sn] = $tags_field } } # Alfred V. Aho, Brian W. Kernighan, Peter J. Weinberger: # The AWK programming language. 1988. p. 161 function qsort(A, left, right, i, last) { if (left >= right) # do nothing if array contains return # less than two elements swap(A, left, left + int((right-left+1)*rand())) last = left # A[left] is now partition element for (i = left+1; i <= right; i++) if (A[i] < A[left]) swap(A, ++last, i) swap(A, left, last) qsort(A, left, last-1) qsort(A, last+1, right) } function swap(A,i,j,t) { t = A[i]; A[i] = A[j]; A[j] = t } FNR == 1 { check_BOMid($1) for (i = 2; i <= NF; i++) column[$i] = i scientific_name_field = column[SCIENTIFIC_NAME] date_field = column[DATE] name_field = column[NAME] note_field = column[NOTES] tags_field = column[TAGS] } $1 == MY_FLORA_ID { if ($scientific_name_field == "") sn = UNKNOWN else sn = $scientific_name_field if (SN_COUNT == 0 || ! (sn in sns)) { sni[++SN_COUNT] = sn sns[sn] = SN_COUNT } # scientific_name[recnr] = sn # name[recnr] = $name_field # date[recnr] = $date_field # notes[recnr] = $note_field # tags[recnr] = $tags_field sn_names[sn] = merge_strings(sn_names[sn], $name_field) sn_dates[sn] = merge_strings(sn_dates[sn], $date_field) sn_notes[sn] = merge_strings(sn_notes[sn], $note_field) sn_tagss[sn] = merge_strings(sn_tagss[sn], $tags_field) } END { if (MODIFICATIONS_FILE != "") apply_modifications(MODIFICATIONS_FILE) else print "No file with modifications to apply." # sorting sni makes sns useless qsort(sni, 1, SN_COUNT) #for (c in column) print c ": " column[c] #for (i in sni) print sni[i] #for (sn in sn_dates) # printf "(%i) %s: %s\t%s\t%s\t%s\n", # sns[sn], sn, sn_names[sn], sn_dates[sn], sn_notes[sn], sn_tagss[sn] #for (i = 1; i in sni; i++) { # sn = sni[i] # printf "(%i) %s: %s\t%s\t%s\t%s\n", # sns[sn], sn, sn_names[sn], sn_dates[sn], sn_notes[sn], sn_tagss[sn] # } #arrays2table(headers, master, arrays) array von arrays geht nicht #arrays2table(FORMAT, headers, sni, sn_names, sn_dates, sn_notes, sn_tagss) fmt[1] = "plain" fmt[2] = "CSV" fmt[3] = "HTML" for (i in fmt) { FORMAT = fmt[i] indexfile = OUT_DIR "/index." tolower(FORMAT) printf "%s", "" > indexfile if (fmt[i] == "plain") format_table(indexfile, map_field_plain, map_field_plain, map_record_plain, map_record_plain, map_table_plain, headers, sni, sn_names, sn_dates, sn_tagss, sn_notes) else if (fmt[i] == "CSV") format_table(indexfile, map_field_csv, map_field_csv, map_record_csv, map_record_csv, map_table_csv, headers, sni, sn_names, sn_dates, sn_tagss, sn_notes) else if (fmt[i] == "HTML") format_table(indexfile, map_field_html_head, map_field_html_data, map_record_html, map_record_html, map_table_html, headers_html, sni, sn_names, sn_dates, sn_tagss, sn_notes) } # Klammern wg. mawk close(indexfile) delete fmt FORMAT = "HTML" cmdfile = OUT_DIR "/" CMD_DOIT logfile = cmdfile ".out" printf "%s", "" > cmdfile for (j = 1; j in sni; j++) { mstr = sni[j] create_subdir_cmd(cmdfile, OUT_DIR "/" mstr) if (sn_dates[mstr] != "") collect_files_cmd(cmdfile, sn_dates[mstr], "*.jpg", OUT_DIR "/" mstr) } close(cmdfile) if (system(CMD_SHELL " -x " cmdfile " > " logfile " 2>&1")) error("Copying files to output directories failed. See " logfile ".") system(CMD_GREP " -v ^+ " logfile " >> /dev/stderr") if (OBSOLETE_SCRIPT != "") system("[ ! -x " OBSOLETE_SCRIPT " ] || " OBSOLETE_SCRIPT) # index.html je Spezies for (j = 1; j in sni; j++) { mstr = sni[j] outdir = OUT_DIR "/" mstr subindexfile = outdir "/index.html" printf PAGE_FORMAT_START, mstr " - " sn_names[mstr] \ > subindexfile format_navigation(subindexfile, sni, sn_names, j) printf PAGE_FORMAT_HEADLINES, mstr, sn_names[mstr] \ > subindexfile format_line(subindexfile, "Markierungen", sn_tagss[mstr]) format_line(subindexfile, "Notizen", sn_notes[mstr]) if (sn_dates[mstr] != "") format_line(subindexfile, "Zeitpunkte (GMT)", normalise_datetimes(sn_dates[mstr])) i = 0 flist = "" # string zuerst in Variable wg. mawk 1.3.4 lscmd = "( cd '" outdir "' && ls " FILE_PATTERN ")" while ( lscmd | getline file == 1) { files[++i] = file flist = merge_strings(flist, file) } #sn_files[mstr] = flist format_images(subindexfile, mstr, files) format_navigation(subindexfile, sni, sn_names, j) output(subindexfile, PAGE_FORMAT_END) close(subindexfile) delete files } }