diff --git a/bin/edit-file-metadata b/bin/edit-file-metadata index 5f10bfc..aadd9a9 100755 --- a/bin/edit-file-metadata +++ b/bin/edit-file-metadata @@ -1,57 +1,138 @@ -#!/usr/bin/env perl +#!/usr/bin/env oil -# A quick script on moving a document with the embedded metadata. -# It uses exiftool for embedding so be sure to have it installed. -# Only needs an argument of a filename to be converted. +# A quick script on moving a file with embedded data. +# It can only detect certain files and write the metadata with a certain program. +# For the argument, it needs the path of the files to be moved. -# TODO: Create --title (-t) option that automatically skips the title prompt. -# TODO: Create --author (-a) option that automatically skips the author prompt. -# TODO: Create --date (-d) option that automatically skips the date prompt. +shopt --set strict:all -use File::Basename; -use File::Copy; -use Modern::Perl; +var help_section = "A script for embedding metadata and renaming them files. -# Create a simple prompt returning with the given answer. -sub prompt { - my ($msg) = @_; - say $msg; - print ">> "; - return ; +edit-file-metadata [options...] FILE + +Options: + -h, --help Show the help section. + -a, --author [AUTHOR] Set the author. + -d, --date [DATE] Set the date. + -t, --title [TITLE] Set the title. + --skip Skip the prompt for missing metadata + and only change the needed metadata. + This only works if you've set any + of the metadata in the command line. + --json Return a JSON object on stdout. + --move Move the filename from the kebab-case + of the title. +" + +var path = '' +var author = '' +var title = '' +var pub_date = '' +var skip = false +var json_data = false +var move = false + +while test $# -gt 0 { + case $1 { + -h|--help) + echo $help_section + shift + ;; + -a|--author) + set author = $2 + shift 2 + ;; + -t|--title) + set title = $2 + shift 2 + ;; + -d|--date) + set pub_date = $2 + shift 2 + ;; + --skip) + set skip = true + shift + ;; + --json) + set json_data = true + shift + ;; + --move) + set move = true + shift + ;; + *) + set path = $1 + shift + ;; + } } -# This implementation of kebab-case conversion is opinionated. -# It converts into lowercase and removes all non-alphanumeric characters. -sub kebab_case { - my ($string) = @_; +proc kebab-case(word) { + # Convert into lower case. + set word = $(echo $word | tr '[:upper:]' '[:lower:]') - # Convert into lowercase. - $string = lc($string); + # What happens to this line: + # * Convert all whitespace and dashes into a single dash. + # * Remove all invalid characters (all that are not alphanumeric characters and dashes). + # * Remove leading and trailing dashes. + set word = $(echo $word | sed --regexp-extended --expression 's/\s+|-+/-/g' --expression 's/[^.a-z0-9-]//g' --expression 's/^-+|-+\$//g') - # Substitute all spaces and extra dashes as one dash. - $string =~ s/\s+|-+/-/g; - - # Remove all invalid characters. - $string =~ s/[^a-z0-9-]//g; - - # Remove all leading and trailing dashes. - $string =~ s/^-+|-+$//g; - - return $string; + echo $word } -my $file = $ARGV[0] ? $ARGV[0] : exit 1; +proc prompt(string, :out, prefix = ">> ") { + >&2 printf "%s\\n%s" $string $prefix + read --line + setref out = $_line +} -# Prompt for all the required information. -my $title = prompt "Title of the document?"; -my $author = prompt "Author?"; -my $publication_date = prompt "Publication date?"; +proc file_parse(path, :out) { + var extension_regex = / '.' ![ '.' ]+ %end / + var file = {} + set file['dir'] = $(dirname $path) + set file['name'] = $(basename $path | sed --regexp-extended "s|(.+)${extension_regex}|\\1|") + set file['ext'] = $(basename $path | sed --regexp-extended "s|.+(${extension_regex})|\\1|") -# Overwrite the file metadata. -system "exiftool -title=\"${title}\" -author=\"${author}\" -date=\"${publication_date}\" \"$file\""; + setref out = file +} -# Once the file metadata has been written, it is time to move the file into its kebab-case equivalent. -my ($filename, $dirs, $suffix) = fileparse($file, '\.[^.]+$'); -my $file_slug = $dirs . kebab_case($title) . $suffix; -move($file, $file_slug); +test -f $path || { + >&2 echo "${path} is not a regular file" + exit 1 +} +# Prompt for the missing metadata (if it's configured to not skip, anyways). +if (not skip) { + test $title || prompt "What is the title?" :title + test $author || prompt "Who are the authors?" :author + test $pub_date || prompt "When this file published?" :pub_date +} + +# Writing up the metadata time! +# Each file type has a different way of embedding metadata so it needs different tools. +# We'll use exiftool as a catch-all since it supports the most out of... 15 file types I considered. +case $(file --mime-type --brief $path) { + "audio/ogg") + vorbiscomment --write $path --tag "TITLE=${title}" --tag "ARTIST=${author}" --tag "DATE=${pub_date}" + ;; + *) + exiftool -title="${title}" -author="${author}" -date="${pub_date}" ${path} + ;; +} + +file_parse $path :file_info + +if (json_data) { + var metadata = {} + set metadata['file'] = file_info + set metadata['title'] = $title + set metadata['author'] = $author + set metadata['date'] = $pub_date + json write :metadata +} + +if (move) { + mv $path "${file_info['dir']}/$(kebab-case $title).${file_info['ext']}" +}