2022-11-11 11:55:09 +00:00
#!/usr/bin/env bash
set -ueo pipefail
2022-11-15 21:01:29 +00:00
[ " ${ DEBUG :- 0 } " = "1" ] && set -x
2022-11-11 11:55:09 +00:00
# usage:
2022-11-12 11:46:34 +00:00
# - init - create an empty database
2022-11-12 22:01:20 +00:00
# - import - import $FILE or import $DIR, both can be multiple values
# - autoimport ($REGEX|video) $FOLDER - will import all files in $FOLDER with a $REGEX filter,
# or one of the preset filters:
# - video
2022-11-11 11:55:09 +00:00
# - add (tag|filename) $VALUE - adds a new tag or filename of $VALUE
# - list (tags|files) - lists all the values in a table
# - bytag $TAG - list all files by tag label
# - tag $FILENAME $TAG - tag $FILENAME with $TAG, $TAG can be repeated
# - listtags $FILENAME - list all tags for $FILENAME
2022-11-15 21:03:38 +00:00
SCRIPT_DIR = $( dirname $( readlink " $0 " ) )
2022-11-16 07:00:00 +00:00
SCRIPT_NAME = $( basename " $0 " )
2022-11-16 07:08:13 +00:00
DB_FILE = " ${ PWD } /tags.db "
2022-11-16 08:02:52 +00:00
[ " ${ 1 :- } " = "--db" ] && DB_FILE = " $2 " && shift 2
2022-11-16 07:00:00 +00:00
2022-11-15 21:03:38 +00:00
DB_SCHEMA = " ${ SCRIPT_DIR } /database.sql "
2022-11-12 22:01:20 +00:00
declare -A FILTERS
FILTERS[ video] = "avi|flv|mkv|mov|mp4|mpg|ogv|webm|wmv"
2022-11-11 11:55:09 +00:00
fail( ) {
echo " $1 " >& 2;
exit 1
}
2022-11-12 11:46:34 +00:00
log( ) {
echo " $1 "
}
2022-11-12 22:01:20 +00:00
init( ) {
2022-11-15 21:16:05 +00:00
# DB_NAME
[ -f " $1 " ] && fail " Database file \" $1 \" already exists. Aborting. "
cat " $DB_SCHEMA " | sqlite3 " $1 "
log " Empty database file \" $1 \" created. "
2022-11-12 22:01:20 +00:00
}
enumerate_positional_parameters( ) {
log " Positional parameters in $FUNCNAME : "
CNT = 0
for VALUE in " $@ " ; do
let CNT++ || true
echo " ${ CNT } : $VALUE "
done
}
2022-11-11 11:55:09 +00:00
listtags( ) {
2022-11-12 22:01:20 +00:00
# $FILENAME $LIMIT=ALL
2022-11-11 11:55:09 +00:00
[ -z " $1 " ] && fail "No filename supplied."
FILENAME = " $1 "
2022-11-11 12:20:11 +00:00
shift
2022-11-16 09:53:07 +00:00
# ! file_exists_in_db "$FILENAME" && fail "File '$FILENAME' does not exist in database."
2022-11-16 08:39:47 +00:00
LIMIT = " ${ 1 :- 0 } "
2022-11-11 12:20:11 +00:00
ADDITIONAL_QUERY = ""
[ $LIMIT -gt 0 ] && ADDITIONAL_QUERY = " LIMIT $LIMIT "
2022-11-12 22:01:20 +00:00
sqlite_query \
2022-11-11 12:20:11 +00:00
" SELECT filename, label from files \
2022-11-16 08:59:44 +00:00
INNER JOIN tags_ties ON tags_ties.fid = files.id \
INNER JOIN tags ON tags.id = tags_ties.tid \
2022-11-16 09:53:07 +00:00
WHERE filename LIKE \" %$FILENAME %\" \
2022-11-11 12:20:11 +00:00
$ADDITIONAL_QUERY "
2022-11-11 11:55:09 +00:00
}
2022-11-12 22:01:20 +00:00
add( ) {
# $TYPE(tag|path|hash) $VALUE1..$VALUEN
[ " $1 " = "tag" ] && shift && add_tag " $@ " && exit 0
[ " $1 " = "path" ] && shift && add_path " $@ " && exit 0
2022-11-16 07:56:58 +00:00
[ " $1 " = "hash" ] && shift && add_hash " $@ " && exit 0
[ " $1 " = "file" ] && fail " Use \" $SCRIPT_NAME add path\" instead. "
fail " Usage: $SCRIPT_NAME add tag/path/hash "
2022-11-12 22:01:20 +00:00
}
2022-11-12 11:46:34 +00:00
2022-11-12 22:01:20 +00:00
sqlite_query( ) {
# $QUERY
2022-11-16 09:53:07 +00:00
dbfile_exists || fail " Database file ' $DB_FILE ' does not exist. Use ' $SCRIPT_NAME init' to create default one, or specify filename with '--db'. "
2022-11-16 07:56:58 +00:00
sqlite3 " $DB_FILE " " $1 "
2022-11-12 22:01:20 +00:00
}
sqlite_lastrows( ) {
# $TABLE $LIMIT
sqlite_query " SELECT * FROM \" $1 \" ORDER BY id DESC LIMIT ${ 2 } "
}
2022-11-16 07:56:58 +00:00
sqlite_insert_single( ) {
2022-11-12 22:01:20 +00:00
# $TABLE $COLUMN $VALUES
# $VALUES can be comma-delimited
[ -z " $1 " ] && fail "No table specified."
TABLE = " $1 "
[ -z " $2 " ] && fail "No column(s) supplied."
COLUMN = " $2 "
[ -z " $3 " ] && fail "No column values supplied."
shift 2
VALUES = " (\" $1 \") "
if [ [ ! -z " ${ 2 :- } " ] ] ; then
while true; do
shift
[ -z " ${ 1 :- } " ] && break
VALUES += " ,(\" $1 \") "
done
fi
2022-11-16 07:56:58 +00:00
QUERY = "PRAGMA foreign_keys=ON;"
QUERY += " INSERT INTO $TABLE ( $COLUMN ) VALUES ${ VALUES } RETURNING *; "
sqlite_query " $QUERY "
}
sqlite_insert_multi( ) {
# $TABLE $COLUMN $VALUE1 $VALUE2
[ -z " $1 " ] && fail "No table specified."
TABLE = " $1 "
[ -z " $2 " ] && fail "No column(s) supplied."
COLUMN = " $2 "
[ [ -z " $3 " || -z " $4 " ] ] && fail "No column values supplied."
shift 2
VALUES = " ( $1 , $2 ) "
if [ [ ! -z " ${ 3 :- } " && ! -z " ${ 4 :- } " ] ] ; then
while true; do
2022-11-16 09:53:07 +00:00
shift 2
[ [ -z " ${ 1 :- } " && -z " ${ 2 :- } " ] ] && break
2022-11-16 07:56:58 +00:00
VALUES += " ,( $1 , $2 ) "
done
fi
QUERY = "PRAGMA foreign_keys=ON;"
QUERY += " INSERT INTO $TABLE ( $COLUMN ) VALUES ${ VALUES } RETURNING *; "
2022-11-12 22:01:20 +00:00
sqlite_query " $QUERY "
}
add_tag( ) {
# $TAG1...$TAGN
TABLE = "tags"
COLUMN = "label"
2022-11-16 07:56:58 +00:00
sqlite_insert_single " $TABLE " " $COLUMN " " $@ "
2022-11-12 22:01:20 +00:00
}
add_path( ) {
# $PATH1..$PATHN
TABLE = "files"
2022-11-16 09:53:07 +00:00
COLUMN = "filename,path"
FILES = ( )
2022-11-16 08:39:47 +00:00
for FILE in " $@ " ; do
2022-11-16 09:53:07 +00:00
FILENAME = $( basename " $FILE " )
FILEPATH = $( dirname " $FILE " )
file_exists_in_db " $FILE " && fail " File ' $FILE ' already exists in database. "
FILES += ( " ' $FILENAME ' " )
FILES += ( " ' $FILEPATH ' " )
2022-11-16 08:39:47 +00:00
done
2022-11-16 09:53:07 +00:00
sqlite_insert_multi " $TABLE " " $COLUMN " " ${ FILES [@] } "
2022-11-16 07:56:58 +00:00
}
add_hash( ) {
# $FILE $HASH
TABLE = "hashes"
COLUMN = "fid,md5"
local FILENAME = " ${ 1 :- } "
[ -z " $FILENAME " ] && fail "No file specified."
2022-11-16 08:39:47 +00:00
! file_exists_in_db " $FILENAME " && fail " File \" $FILENAME \" does not exist in database. "
2022-11-16 07:56:58 +00:00
sqlite_insert_multi " $TABLE " " $COLUMN " $RESULT " ' $2 ' "
2022-11-12 22:01:20 +00:00
}
add_path_auto( ) {
# $REGEX $FOLDER
find " ${ 2 } " -type f -regextype posix-extended -iregex " $1 " -exec " $0 " import "{}" +
}
2022-11-16 08:35:49 +00:00
tag_exists_in_db( ) {
# $TAGLABEL
TAG = ${ 1 :- }
RESULT = $( sqlite_query " SELECT id FROM tags WHERE label = ' $TAG ' " )
if [ [ -z " $RESULT " ] ] ; then
return 1
else
return 0
fi
}
2022-11-16 08:39:47 +00:00
file_exists_in_db( ) {
# $FILENAME
2022-11-16 09:53:07 +00:00
FILENAME = $( basename " ${ 1 :- } " )
FILEPATH = $( dirname " ${ 1 :- } " )
RESULT = $( sqlite_query " SELECT id FROM files WHERE filename = ' $FILENAME ' AND path = ' $FILEPATH ' " )
2022-11-16 08:39:47 +00:00
if [ [ -z " $RESULT " ] ] ; then
return 1
else
return 0
fi
}
2022-11-16 09:53:07 +00:00
dbfile_exists( ) {
if [ [ ! -f " $DB_FILE " ] ] ; then
return 1
else
return 0
fi
}
2022-11-12 22:01:20 +00:00
main( ) {
2022-11-16 08:02:52 +00:00
[ -z " ${ 1 :- } " ] && fail "Usage: tag init/add/import/autoimport/list/listtags"
2022-11-12 22:01:20 +00:00
if [ [ " $1 " = "init" ] ] ; then
2022-11-15 21:16:05 +00:00
init " ${ 2 :- $DB_FILE } "
2022-11-12 22:01:20 +00:00
exit 0
fi
if [ [ " $1 " = "import" ] ] ; then
2022-11-11 11:55:09 +00:00
shift
2022-11-12 22:01:20 +00:00
add "path" " $@ "
fi
2022-11-11 11:55:09 +00:00
2022-11-12 22:01:20 +00:00
if [ [ " $1 " = "autoimport" ] ] ; then
shift
if [ [ " ${ 1 :- } " = ~ " ${ !FILTERS[@] } " ] ] ; then
add_path_auto " .*( ${ FILTERS [ $1 ] } ) " " $2 "
else
add_path_auto " $1 " " $2 "
fi
fi
2022-11-11 11:55:09 +00:00
2022-11-12 22:01:20 +00:00
if [ [ " $1 " = "add" ] ] ; then
shift
add " $@ "
fi
2022-11-11 11:55:09 +00:00
2022-11-12 22:01:20 +00:00
if [ [ " $1 " = "list" ] ] ; then
[ -z " $2 " ] && fail "No table supplied."
TABLE_NAME = " $2 "
2022-11-16 09:53:07 +00:00
sqlite_query " SELECT * FROM \" ${ TABLE_NAME } \" "
2022-11-12 22:01:20 +00:00
exit 0
fi
if [ [ " $1 " = "bytag" ] ] ; then
[ -z " $2 " ] && fail "No tag supplied."
TAG_NAME = " $2 "
2022-11-16 09:53:07 +00:00
sqlite_query " SELECT filename FROM files WHERE id = (SELECT id FROM tags_ties WHERE id = (SELECT id FROM tags WHERE label = \" ${ TAG_NAME } \")) "
2022-11-12 22:01:20 +00:00
exit 0
fi
if [ [ " $1 " = "tag" ] ] ; then
2022-11-11 11:55:09 +00:00
shift
2022-11-16 08:39:47 +00:00
[ -z " ${ 1 :- } " ] && fail "No filename supplied."
2022-11-12 22:01:20 +00:00
FILENAME = " $1 "
2022-11-16 08:39:47 +00:00
! file_exists_in_db " $FILENAME " && fail " File ' $FILENAME ' does not exist in database. "
2022-11-12 22:01:20 +00:00
shift
2022-11-16 08:35:49 +00:00
[ -z " ${ 1 :- } " ] && fail "No tag supplied."
2022-11-12 22:01:20 +00:00
COUNTER = 0
while true; do
LABEL = " $1 "
2022-11-16 08:35:49 +00:00
! tag_exists_in_db " $LABEL " && fail " Tag ' $TAG ' does not exist in database. "
2022-11-12 22:01:20 +00:00
shift
2022-11-16 08:59:44 +00:00
sqlite_query " INSERT INTO tags_ties (fid, tid) VALUES ((SELECT id FROM files WHERE filename = \" $FILENAME \"),(SELECT id FROM tags WHERE label = \" $LABEL \")) "
2022-11-12 22:01:20 +00:00
COUNTER = $(( COUNTER++))
[ -z " ${ 1 :- } " ] && break
done
listtags " $FILENAME " " $COUNTER "
exit 0
fi
2022-11-11 11:55:09 +00:00
2022-11-12 22:01:20 +00:00
if [ [ " $1 " = "listtags" ] ] ; then
2022-11-16 07:00:13 +00:00
[ -z " ${ 2 :- } " ] && fail " Usage: $SCRIPT_NAME listtags filename "
2022-11-12 22:01:20 +00:00
listtags " $2 "
exit 0
fi
}
main " $@ "
2022-11-11 11:55:09 +00:00