dotfiles/bin/edit-file-metadata
2021-04-09 19:21:26 +08:00

139 lines
3.7 KiB
Plaintext
Executable File

#!/usr/bin/env oil
# 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.
shopt --set strict:all
var help_section = "A script for embedding metadata and renaming them files.
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
;;
}
}
proc kebab-case(word) {
# Convert into lower case.
set word = $(echo $word | tr '[:upper:]' '[:lower:]')
# 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')
echo $word
}
proc prompt(string, :out, prefix = ">> ") {
>&2 printf "%s\\n%s" $string $prefix
read --line
setref out = $_line
}
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|")
setref out = file
}
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']}"
}