From 8be0d386e760f95bad8371495af54686d5505550 Mon Sep 17 00:00:00 2001 From: "Arnaud G. GIBERT" Date: Sun, 12 Apr 2026 19:37:08 +0200 Subject: [PATCH] - Migrate album_retitle, music_folder_make, music_info & music_tag_cleaner, - Add album_retitle, music_folder_make, music_info & music_tag_cleaner completion script. --- bin/album_convert | 2 +- bin/album_merge | 6 +- bin/album_metadata_load | 2 +- bin/album_metadata_save | 1 + bin/album_renum | 4 + bin/album_retitle | 204 ++++++++-- bin/music-info | 498 ++++++++++++++++-------- bin/music_folder_make | 186 +++++---- bin/music_tag_cleanner | 235 ++++++----- etc/bash_completion.d/album_retitle | 95 +++++ etc/bash_completion.d/music_folder_make | 64 +++ etc/bash_completion.d/music_info | 59 +++ etc/bash_completion.d/music_tag_cleaner | 71 ++++ 13 files changed, 1060 insertions(+), 367 deletions(-) create mode 100644 etc/bash_completion.d/album_retitle create mode 100644 etc/bash_completion.d/music_folder_make create mode 100644 etc/bash_completion.d/music_info create mode 100644 etc/bash_completion.d/music_tag_cleaner diff --git a/bin/album_convert b/bin/album_convert index d3381e8..33582d0 100755 --- a/bin/album_convert +++ b/bin/album_convert @@ -111,7 +111,7 @@ ac_args_parse() -r|--resample) RESAMPLE="TRUE"; shift;; -d|--downsampled_tag) DSTAG="TRUE"; shift;; - # + # End of options --) shift; break;; *) echo "args_parse internal error [$1] !"; exit 1;; esac diff --git a/bin/album_merge b/bin/album_merge index 1d612b9..8895053 100755 --- a/bin/album_merge +++ b/bin/album_merge @@ -109,9 +109,9 @@ am_args_parse() # Global options -v|--verbose) VERBOSE="TRUE"; shift;; - # - --) shift; break;; - *) echo "args_parse internal error [$1] !"; exit 1;; + # End of options + --) shift; break;; + *) echo "args_parse internal error [$1] !"; exit 1;; esac done diff --git a/bin/album_metadata_load b/bin/album_metadata_load index adaa789..2fb7266 100755 --- a/bin/album_metadata_load +++ b/bin/album_metadata_load @@ -110,7 +110,7 @@ aml_args_parse() -v|--verbose) VERBOSE="TRUE"; shift;; -c|--clean) CLEAN="TRUE"; shift;; - # + # End of options --) shift; break;; *) echo "args_parse internal error [$1] !"; exit 1;; esac diff --git a/bin/album_metadata_save b/bin/album_metadata_save index c4e4389..66af47e 100755 --- a/bin/album_metadata_save +++ b/bin/album_metadata_save @@ -108,6 +108,7 @@ ams_args_parse() -f|--factoring) FACTORING="TRUE"; shift;; -s|--standardising) STANDARDISING="TRUE"; shift;; + # End of options --) shift; break;; *) echo_error "args_parse internal error [$1]!"; exit 1;; esac diff --git a/bin/album_renum b/bin/album_renum index b6521eb..a48bf52 100755 --- a/bin/album_renum +++ b/bin/album_renum @@ -55,6 +55,7 @@ declare -g DRY_RUN="FALSE" + #----------------------------------------------------------------------------------------------------------------------------------- # Version Print #----------------------------------------------------------------------------------------------------------------------------------- @@ -67,6 +68,7 @@ ar_version_print() + #----------------------------------------------------------------------------------------------------------------------------------- # Help Print #----------------------------------------------------------------------------------------------------------------------------------- @@ -80,6 +82,7 @@ ar_help_print() + #----------------------------------------------------------------------------------------------------------------------------------- # Arg Parse #----------------------------------------------------------------------------------------------------------------------------------- @@ -137,6 +140,7 @@ ar_args_parse() + #----------------------------------------------------------------------------------------------------------------------------------- # Main #----------------------------------------------------------------------------------------------------------------------------------- diff --git a/bin/album_retitle b/bin/album_retitle index 8e51a34..8342e33 100755 --- a/bin/album_retitle +++ b/bin/album_retitle @@ -1,48 +1,194 @@ #!/bin/bash +#----------------------------------------------------------------------------------------------------------------------------------- +# +# Album Retitle +# +# Copyright (C) 2016-2026 Arnaud G. GIBERT +# mailto:arnaud@rx3.net +# +# This is free software: you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; If not, see +# . +# +#----------------------------------------------------------------------------------------------------------------------------------- -function fix_file_name + + +#----------------------------------------------------------------------------------------------------------------------------------- +# Includes +#----------------------------------------------------------------------------------------------------------------------------------- + +: "${RX3_LIB_DIR:=/usr/lib/rx3}" +. "${RX3_LIB_DIR}/music_tools.bash" + + + + + +#----------------------------------------------------------------------------------------------------------------------------------- +# Global Variables +#----------------------------------------------------------------------------------------------------------------------------------- + +declare -g VERSION="1.0.0" +declare -g NAME="album_retitle" +declare -g HELP="usage: [-h | --help] | [-V | --version] | [-T | --test] [-v | --verbose] " + +declare -g SOURCE_DIR="" +declare -g TARGET_DIR="" +declare -g TITLE_FILE="" + +declare -g MODE="DEFAULT" +declare -g VERBOSE="FALSE" +declare -g DRY_RUN="FALSE" + + + + + +#----------------------------------------------------------------------------------------------------------------------------------- +# Version Print +#----------------------------------------------------------------------------------------------------------------------------------- + +ar_version_print() { - input="$1" - -# echo ${input} | sed -e 's/ /_/g' -e "s/'/_/g" -e 's/_(/-/g' -e 's/)//g' -e 's/_-_/-/g' -e 's/\//_/g' | tr '[:upper:]' '[:lower:]' - echo ${input} | sed -e 's/\(^[0-9]*\)./\1-/' -e 's/[ ,!/?]/_/g' -e 's/\[/-/g' -e 's/\]//g' -e "s/'/_/g" -e 's/(/-/g' -e 's/)//g' -e 's/__/_/g' -e 's/_\././' -e 's/_-/-/g' -e 's/--/-/g' -e 's/-_/-/g' -e 's/é/e/g' -e 's/è/e/g' -e 's/ê/e/g' -e 's/ë/e/g' -e 's/à/a/g' -e 's/[+&]/and/' -e 's/^-//' -e 's/"/_inch/' | tr '[:upper:]' '[:lower:]' + version_print } -shopt -s extglob -if [[ "$1" == "-h" ]] + +#----------------------------------------------------------------------------------------------------------------------------------- +# Help Print +#----------------------------------------------------------------------------------------------------------------------------------- + +ar_help_print() +{ + ar_version_print + help_print +} + + + + + +#----------------------------------------------------------------------------------------------------------------------------------- +# Arg Parse +#----------------------------------------------------------------------------------------------------------------------------------- + +ar_args_parse() +{ + tmp_args=$(getopt -o ThVv --long test,help,version,verbose -n "${NAME}" -- "$@") + + if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi + + # Note the quotes around `$TEMP': they are essential! + eval set -- "${tmp_args}" + + while true + do + case "$1" in + # Options + + # Mode switches + -T|--test) MODE="TEST"; shift;; + -h|--help) MODE="EXIT"; ar_help_print; shift;; + -V|--version) MODE="EXIT"; ar_version_print; shift;; + + # Global options + -v|--verbose) VERBOSE="TRUE"; shift;; + + # End of options + --) shift; break;; + *) echo "args_parse internal error [$1] !"; exit 1;; + esac + done + + if [[ "${MODE}" != "EXIT" ]] + then + if [[ "${#}" != "3" ]] + then + if [[ "${#}" -lt "3" ]] + then + echo_error "Not enough args!" + else + echo_error "Too many args!" + fi + + MODE="EXIT" + ar_help_print + else + SOURCE_DIR="$1" + TARGET_DIR="$2" + TITLE_FILE="$3" + fi + fi +} + + + + +#----------------------------------------------------------------------------------------------------------------------------------- +# Main +#----------------------------------------------------------------------------------------------------------------------------------- + +ar_args_parse "$@" + + + +if [[ "${MODE}" == "EXIT" ]] then - echo "album_retitle [-h] | " - exit + exit 0 +else + if [[ "${MODE}" == "TEST" ]] + then + DRY_RUN="TRUE" + fi fi -source_dir="$1" -target_dir="$2" -title_file="$3" + + +echo_error "${NAME}: Mode: [${MODE}] Verbose: [${VERBOSE}] Source_Dir: [${SOURCE_DIR}] Target_Dir: [${TARGET_DIR}] Title_File: [${TITLE_FILE}]" + +if [[ ! -d "${TARGET_DIR}" ]] +then + echo_error "Target directory doesn't exist !" + exit -1 +fi + +if [[ ! -f "${TITLE_FILE}" ]] +then + echo_error "Title file doesn't exist !" + exit -1 +fi i=1 -while read title +while read -r title do - file=(${source_dir}/$(printf %02d $i)-*.@(flac|mp3)) - suffix=${file##*.} - target_file="${target_dir}/$( fix_file_name $( fix_file_name $( fix_file_name $(printf "%02d" $i)-"${title}.${file##*.}")))" + j=$(printf "%02d" "${i}") + file=("${SOURCE_DIR}"/${j}-*.@(.flac|.mp3)) + suffix="${file##*.}" + target_file="${TARGET_DIR}/$(mt_fix_file_name "${j}-${title}.${suffix}")" - echo "${target_file}: '"${title}"'" - cp "${file}" "${target_file}" + echo_error "${NAME}: [${file}] -> [${target_file}]" - case "${suffix}" - in - flac) - metaflac --remove-tag=TRACKNUMBER --set-tag=TRACKNUMBER=$i --remove-tag=TITLE --set-tag=TITLE="${title}" "${target_file}" - ;; + cmd_exec cp "${file}" "${target_file}" - mp3) - mid3v2 -T $i -t "${title}" "${target_file}" - ;; - esac + mt_tag_delete "${target_file}" "TRACKNUMBER" + mt_tag_delete "${target_file}" "TITLE" + mt_tag_write "${target_file}" "TRACKNUMBER" "${j}" + mt_tag_write "${target_file}" "TITLE" "${title}" - i=$(($i + 1)) -done < ${title_file} + i=$(( i + 1 )) +done < "${TITLE_FILE}" diff --git a/bin/music-info b/bin/music-info index d9ba7c1..72d941c 100755 --- a/bin/music-info +++ b/bin/music-info @@ -1,182 +1,360 @@ #!/bin/bash +#----------------------------------------------------------------------------------------------------------------------------------- +# +# Music Info +# +# Copyright (C) 2016-2026 Arnaud G. GIBERT +# mailto:arnaud@rx3.net +# +# This is free software: you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; If not, see +# . +# +#----------------------------------------------------------------------------------------------------------------------------------- -default_top=/opt/music/src -function list + +#----------------------------------------------------------------------------------------------------------------------------------- +# Includes +#----------------------------------------------------------------------------------------------------------------------------------- + +: "${RX3_LIB_DIR:=/usr/lib/rx3}" +. "${RX3_LIB_DIR}/music_tools.bash" + + + + + +#----------------------------------------------------------------------------------------------------------------------------------- +# Global Variables +#----------------------------------------------------------------------------------------------------------------------------------- + +declare -g VERSION="1.0.0" +declare -g NAME="music_info" +declare -g HELP="usage: [-h | --help] | [-V | --version] | [-l | --list] [-r | --root_dir ]" + +declare -g ROOT_DIR="/opt/music/src" + +declare -g MODE="STATS" +declare -g VERBOSE="FALSE" +declare -g DRY_RUN="FALSE" + + + + + +#----------------------------------------------------------------------------------------------------------------------------------- +# Version Print +#----------------------------------------------------------------------------------------------------------------------------------- + +mi_version_print() { - type="$1" - suffix="$2" - - case $type in - "track") - find $top -type f | grep "\.${suffix}$" - ;; - - "lp"|"ep"|"single"|"live"|"compilation"|"tribute") - find $top -type f | grep -v -e "/child/" -e "/original_soundtrack/" -e "/various_artists/" | grep -e "/${type}/" | grep "\.${suffix}$" | sed -e 's/\/[^/]*$//' | sort -u - ;; - - "child") - find $top -type f | grep -e "/child/" | grep "\.${suffix}$" | sed -e 's/\/[^/]*$//' | sort -u - ;; - - "ost") - find $top -type f | grep -e "/original_soundtrack/" | grep "\.${suffix}$" | sed -e 's/\/[^/]*$//' | sort -u - ;; - - "va") - find $top -type f | grep -e "/various_artists/" | grep "\.${suffix}$" | sed -e 's/\/[^/]*$//' | sort -u - ;; - - "us") - find $top -type f | grep -v -e "/various_artists/" -e "/original_soundtrack/" -e "/lp/" -e "/ep/" -e "/single/" -e "/live/" -e "/compilation/" -e '/misc/' -e "/tribute/" | grep "\.${suffix}$" | sed -e 's/\/[^/]*$//' | sort -u - ;; - - esac -} - -function count -{ - type="$1" - suffix="$2" - - echo "$( list ${type} ${suffix} | wc -l)" + version_print } -if [[ "$1" == "-l" ]] -then - mode="list" - shift -else - mode="stats" -fi -arg_top="$1" -if [[ "${arg_top}" != "" ]] -then - top="$(realpath ${arg_top})" -else - top="${default_top}" -fi +#----------------------------------------------------------------------------------------------------------------------------------- +# Help Print +#----------------------------------------------------------------------------------------------------------------------------------- + +mi_help_print() +{ + mi_version_print + help_print +} -if [[ "${mode}" == "stats" ]] -then - track_flac="$(count track flac)" - track_ogg="$(count track ogg)" - track_mp3="$(count track mp3)" - track_music=$((${track_flac} + ${track_ogg} + ${track_mp3})) - track_avi="$(count track avi)" - track_mp4="$(count track mp4)" - track_mkv="$(count track mkv)" - track_video=$((${track_avi} + ${track_mp4} + ${track_mkv})) +#----------------------------------------------------------------------------------------------------------------------------------- +# Arg Parse +#----------------------------------------------------------------------------------------------------------------------------------- - track_jpg="$(count track jpg)" - track_png="$(count track png)" -track_picture=$((${track_jpg} + ${track_png})) +mi_args_parse() +{ + tmp_args=$(getopt -o r:lhVv --long root_dir:,list,help,version,verbose -n "${NAME}" -- "$@") - track_total=$((${track_music} + ${track_video} + ${track_picture})) + if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi - lp_flac="$(count lp flac)" - lp_ogg="$(count lp ogg)" - lp_mp3="$(count lp mp3)" - lp_music=$((${lp_flac} + ${lp_ogg} + ${lp_mp3})) + # Note the quotes around `$TEMP': they are essential! + eval set -- "${tmp_args}" - ep_flac="$(count ep flac)" - ep_ogg="$(count ep ogg)" - ep_mp3="$(count ep mp3)" - ep_music=$((${ep_flac} + ${ep_ogg} + ${ep_mp3})) - - single_flac="$(count single flac)" - single_ogg="$(count single ogg)" - single_mp3="$(count single mp3)" - single_music=$((${single_flac} + ${single_ogg} + ${single_mp3})) - - live_flac="$(count live flac)" - live_ogg="$(count live ogg)" - live_mp3="$(count live mp3)" - live_music=$((${live_flac} + ${live_ogg} + ${live_mp3})) - - compilation_flac="$(count compilation flac)" - compilation_ogg="$(count compilation ogg)" - compilation_mp3="$(count compilation mp3)" -compilation_music=$((${compilation_flac} + ${compilation_ogg} + ${compilation_mp3})) - - tribute_flac="$(count tribute flac)" - tribute_ogg="$(count tribute ogg)" - tribute_mp3="$(count tribute mp3)" -tribute_music=$((${tribute_flac} + ${tribute_ogg} + ${tribute_mp3})) - - child_flac="$(count child flac)" - child_ogg="$(count child ogg)" - child_mp3="$(count child mp3)" - child_music=$((${child_flac} + ${child_ogg} + ${child_mp3})) - - ost_flac="$(count ost flac)" - ost_ogg="$(count ost ogg)" - ost_mp3="$(count ost mp3)" - ost_music=$((${ost_flac} + ${ost_ogg} + ${ost_mp3})) - - va_flac="$(count va flac)" - va_ogg="$(count va ogg)" - va_mp3="$(count va mp3)" - va_music=$((${va_flac} + ${va_ogg} + ${va_mp3})) - - us_flac="$(count us flac)" - us_ogg="$(count us ogg)" - us_mp3="$(count us mp3)" - us_music=$((${us_flac} + ${us_ogg} + ${us_mp3})) - -set_flac_total=$((${lp_flac} + ${ep_flac} + ${single_flac} + ${live_flac} + ${compilation_flac} + ${tribute_flac} + ${child_flac} + ${ost_flac} + ${va_flac} + ${us_flac})) - set_ogg_total=$((${lp_ogg} + ${ep_ogg} + ${single_ogg} + ${live_ogg} + ${compilation_ogg} + ${tribute_ogg} + ${child_ogg} + ${ost_ogg} + ${va_ogg} + ${us_ogg})) - set_mp3_total=$((${lp_mp3} + ${ep_mp3} + ${single_mp3} + ${live_mp3} + ${compilation_mp3} + ${tribute_mp3} + ${child_mp3} + ${ost_mp3} + ${va_mp3} + ${us_mp3})) - set_total=$((${lp_music} + ${ep_music} + ${single_music} + ${live_music} + ${compilation_music} + ${tribute_music} + ${child_music} + ${ost_music} + ${va_music} + ${us_music})) - - echo "Music Statistics from ${top}:" - echo "Tracks:" - printf "Music: Flac: %5s OGG: %5s MP3: %5s Total: %6s\n" ${track_flac} ${track_ogg} ${track_mp3} ${track_music} - printf "Video: AVI: %5s mp4: %5s MKV: %5s Total: %6s\n" ${track_avi} ${track_mp4} ${track_mkv} ${track_video} - printf "Picture: JPG: %5s PNG: %5s %5s Total: %6s\n" ${track_jpg} ${track_png} "" ${track_picture} - printf " %5s %5s %5s Total: %6s\n" "" "" "" ${track_total} - - echo "" - echo "Album | Flac | OGG | MP3 || Total" - echo "---------+-------+-------+-------++------" - printf "LP | %5s | %5s | %5s || %5s\n" ${lp_flac} ${lp_ogg} ${lp_mp3} ${lp_music} - printf "EP | %5s | %5s | %5s || %5s\n" ${ep_flac} ${ep_ogg} ${ep_mp3} ${ep_music} - printf "Single | %5s | %5s | %5s || %5s\n" ${single_flac} ${single_ogg} ${single_mp3} ${single_music} - printf "Live | %5s | %5s | %5s || %5s\n" ${live_flac} ${live_ogg} ${live_mp3} ${live_music} - printf "Compil | %5s | %5s | %5s || %5s\n" ${compilation_flac} ${compilation_ogg} ${compilation_mp3} ${compilation_music} - printf "Tribute | %5s | %5s | %5s || %5s\n" ${tribute_flac} ${tribute_ogg} ${tribute_mp3} ${tribute_music} - printf "Child | %5s | %5s | %5s || %5s\n" ${child_flac} ${child_ogg} ${child_mp3} ${child_music} - printf "OST | %5s | %5s | %5s || %5s\n" ${ost_flac} ${ost_ogg} ${ost_mp3} ${ost_music} - printf "VA | %5s | %5s | %5s || %5s\n" ${va_flac} ${va_ogg} ${va_mp3} ${va_music} - printf "UnSorted | %5s | %5s | %5s || %5s\n" ${us_flac} ${us_ogg} ${us_mp3} ${us_music} - echo "---------+-------+-------+-------++------" - printf "Total | %5s | %5s | %5s || %5s\n" ${set_flac_total} ${set_ogg_total} ${set_mp3_total} ${set_total} - -else - - for suffix in flac ogg mp3 avi mp4 mkv jpg png - do - echo "Track ${suffix}:" - list track ${suffix} | sed -e "s/^/track /" - echo - done - - for type in lp ep single live compilation tribute va ost us - do - for suffix in flac ogg mp3 + while true do - echo "Set ${type} ${suffix}:" - list ${type} ${suffix} | sed -e "s/^/${type} /" - echo + case "$1" in + # Options + -r|--root_dir) shift; ROOT_DIR="$1"; shift;; + + # Mode switches + -l|--list) MODE="LIST"; shift;; + -h|--help) MODE="EXIT"; mi_help_print; shift;; + -V|--version) MODE="EXIT"; mi_version_print; shift;; + + # Global options + -v|--verbose) VERBOSE="TRUE"; shift;; + + # End of options + --) shift; break;; + *) echo "args_parse internal error [$1] !"; exit 1;; + esac done - done + + if [[ "${MODE}" != "EXIT" ]] + then + if [[ "${#}" -gt "0" ]] + then + echo_error "Too many args!" + + MODE="EXIT" + mi_help_print + fi + fi +} + + + + + +#----------------------------------------------------------------------------------------------------------------------------------- +# List +#----------------------------------------------------------------------------------------------------------------------------------- + +mi_list() +{ + local type="$1" + local suffix="$2" + + + case "${type}" + in + track) + find "${ROOT_DIR}" -type f | grep "\\.${suffix}$" + ;; + + lp|ep|single|live|compilation|tribute) + find "${ROOT_DIR}" -type f | grep -v -e "/child/" -e "/original_soundtrack/" -e "/various_artists/" | grep -e "/${type}/" | grep "\\.${suffix}$" | sed -e 's/\/[^/]*$//' | sort -u + ;; + + child) + find "${ROOT_DIR}" -type f | grep -e "/child/" | grep "\\.${suffix}$" | sed -e 's/\/[^/]*$//' | sort -u + ;; + + ost) + find "${ROOT_DIR}" -type f | grep -e "/original_soundtrack/" | grep "\\.${suffix}$" | sed -e 's/\/[^/]*$//' | sort -u + ;; + + va) + find "${ROOT_DIR}" -type f | grep -e "/various_artists/" | grep "\\.${suffix}$" | sed -e 's/\/[^/]*$//' | sort -u + ;; + + us) + find "${ROOT_DIR}" -type f | grep -v -e "/various_artists/" -e "/original_soundtrack/" -e "/lp/" -e "/ep/" -e "/single/" -e "/live/" -e "/compilation/" -e "/misc/" -e "/tribute/" | grep "\\.${suffix}$" | sed -e 's/\/[^/]*$//' | sort -u + ;; + esac +} + + + + + +#----------------------------------------------------------------------------------------------------------------------------------- +# Count +#----------------------------------------------------------------------------------------------------------------------------------- + +mi_count() +{ + local type="$1" + local suffix="$2" + + + echo "$(mi_list "${type}" "${suffix}" | wc -l)" +} + + + + + +#----------------------------------------------------------------------------------------------------------------------------------- +# Stats Print +#----------------------------------------------------------------------------------------------------------------------------------- + +mi_stats_print() +{ + local track_flac=$(mi_count track flac) + local track_ogg=$(mi_count track ogg) + local track_mp3=$(mi_count track mp3) + local track_music=$(( track_flac + track_ogg + track_mp3 )) + + local track_avi=$(mi_count track avi) + local track_mp4=$(mi_count track mp4) + local track_mkv=$(mi_count track mkv) + local track_video=$(( track_avi + track_mp4 + track_mkv )) + + local track_jpg=$(mi_count track jpg) + local track_png=$(mi_count track png) + local track_picture=$(( track_jpg + track_png )) + + local track_total=$(( track_music + track_video + track_picture )) + + local lp_flac=$(mi_count lp flac) + local lp_ogg=$(mi_count lp ogg) + local lp_mp3=$(mi_count lp mp3) + local lp_music=$(( lp_flac + lp_ogg + lp_mp3 )) + + local ep_flac=$(mi_count ep flac) + local ep_ogg=$(mi_count ep ogg) + local ep_mp3=$(mi_count ep mp3) + local ep_music=$(( ep_flac + ep_ogg + ep_mp3 )) + + local single_flac=$(mi_count single flac) + local single_ogg=$(mi_count single ogg) + local single_mp3=$(mi_count single mp3) + local single_music=$(( single_flac + single_ogg + single_mp3 )) + + local live_flac=$(mi_count live flac) + local live_ogg=$(mi_count live ogg) + local live_mp3=$(mi_count live mp3) + local live_music=$(( live_flac + live_ogg + live_mp3 )) + + local compilation_flac=$(mi_count compilation flac) + local compilation_ogg=$(mi_count compilation ogg) + local compilation_mp3=$(mi_count compilation mp3) + local compilation_music=$(( compilation_flac + compilation_ogg + compilation_mp3 )) + + local tribute_flac=$(mi_count tribute flac) + local tribute_ogg=$(mi_count tribute ogg) + local tribute_mp3=$(mi_count tribute mp3) + local tribute_music=$(( tribute_flac + tribute_ogg + tribute_mp3 )) + + local child_flac=$(mi_count child flac) + local child_ogg=$(mi_count child ogg) + local child_mp3=$(mi_count child mp3) + local child_music=$(( child_flac + child_ogg + child_mp3 )) + + local ost_flac=$(mi_count ost flac) + local ost_ogg=$(mi_count ost ogg) + local ost_mp3=$(mi_count ost mp3) + local ost_music=$(( ost_flac + ost_ogg + ost_mp3 )) + + local va_flac=$(mi_count va flac) + local va_ogg=$(mi_count va ogg) + local va_mp3=$(mi_count va mp3) + local va_music=$(( va_flac + va_ogg + va_mp3 )) + + local us_flac=$(mi_count us flac) + local us_ogg=$(mi_count us ogg) + local us_mp3=$(mi_count us mp3) + local us_music=$(( us_flac + us_ogg + us_mp3 )) + + local set_flac_total=$(( lp_flac + ep_flac + single_flac + live_flac + compilation_flac + tribute_flac + child_flac + ost_flac + va_flac + us_flac )) + local set_ogg_total=$(( lp_ogg + ep_ogg + single_ogg + live_ogg + compilation_ogg + tribute_ogg + child_ogg + ost_ogg + va_ogg + us_ogg )) + local set_mp3_total=$(( lp_mp3 + ep_mp3 + single_mp3 + live_mp3 + compilation_mp3 + tribute_mp3 + child_mp3 + ost_mp3 + va_mp3 + us_mp3 )) + local set_total=$(( lp_music + ep_music + single_music + live_music + compilation_music + tribute_music + child_music + ost_music + va_music + us_music )) + + + echo "Music Statistics from ${ROOT_DIR}:" + echo "Tracks:" + printf "Music: Flac: %5s OGG: %5s MP3: %5s Total: %6s\n" "${track_flac}" "${track_ogg}" "${track_mp3}" "${track_music}" + printf "Video: AVI: %5s mp4: %5s MKV: %5s Total: %6s\n" "${track_avi}" "${track_mp4}" "${track_mkv}" "${track_video}" + printf "Picture: JPG: %5s PNG: %5s %5s Total: %6s\n" "${track_jpg}" "${track_png}" "" "${track_picture}" + printf " %5s %5s %5s Total: %6s\n" "" "" "" "${track_total}" + + echo "" + echo "Album | Flac | OGG | MP3 || Total" + echo "---------+-------+-------+-------++------" + printf "LP | %5s | %5s | %5s || %5s\n" "${lp_flac}" "${lp_ogg}" "${lp_mp3}" "${lp_music}" + printf "EP | %5s | %5s | %5s || %5s\n" "${ep_flac}" "${ep_ogg}" "${ep_mp3}" "${ep_music}" + printf "Single | %5s | %5s | %5s || %5s\n" "${single_flac}" "${single_ogg}" "${single_mp3}" "${single_music}" + printf "Live | %5s | %5s | %5s || %5s\n" "${live_flac}" "${live_ogg}" "${live_mp3}" "${live_music}" + printf "Compil | %5s | %5s | %5s || %5s\n" "${compilation_flac}" "${compilation_ogg}" "${compilation_mp3}" "${compilation_music}" + printf "Tribute | %5s | %5s | %5s || %5s\n" "${tribute_flac}" "${tribute_ogg}" "${tribute_mp3}" "${tribute_music}" + printf "Child | %5s | %5s | %5s || %5s\n" "${child_flac}" "${child_ogg}" "${child_mp3}" "${child_music}" + printf "OST | %5s | %5s | %5s || %5s\n" "${ost_flac}" "${ost_ogg}" "${ost_mp3}" "${ost_music}" + printf "VA | %5s | %5s | %5s || %5s\n" "${va_flac}" "${va_ogg}" "${va_mp3}" "${va_music}" + printf "UnSorted | %5s | %5s | %5s || %5s\n" "${us_flac}" "${us_ogg}" "${us_mp3}" "${us_music}" + echo "---------+-------+-------+-------++------" + printf "Total | %5s | %5s | %5s || %5s\n" "${set_flac_total}" "${set_ogg_total}" "${set_mp3_total}" "${set_total}" +} + + + + + +#----------------------------------------------------------------------------------------------------------------------------------- +# List Print +#----------------------------------------------------------------------------------------------------------------------------------- + +mi_list_print() +{ + local suffix type + + + for suffix in flac ogg mp3 avi mp4 mkv jpg png + do + echo "Track ${suffix}:" + mi_list track "${suffix}" | sed -e "s/^/track /" + echo + done + + for type in lp ep single live compilation tribute va ost us + do + for suffix in flac ogg mp3 + do + echo "Set ${type} ${suffix}:" + mi_list "${type}" "${suffix}" | sed -e "s/^/${type} /" + echo + done + done +} + + + + + +#----------------------------------------------------------------------------------------------------------------------------------- +# Main +#----------------------------------------------------------------------------------------------------------------------------------- + +mi_args_parse "$@" + + + +if [[ "${MODE}" == "EXIT" ]] +then + exit 0 fi + + + +echo_error "${NAME}: Mode: [${MODE}] Verbose: [${VERBOSE}] Root_Dir: [${ROOT_DIR}]" + +if [[ ! -d "${ROOT_DIR}" ]] +then + echo_error "Root directory doesn't exist !" + exit -1 +fi + +case "${MODE}" +in + STATS) + mi_stats_print + ;; + + LIST) + mi_list_print + ;; +esac diff --git a/bin/music_folder_make b/bin/music_folder_make index 37dabb1..20b1d71 100755 --- a/bin/music_folder_make +++ b/bin/music_folder_make @@ -1,84 +1,117 @@ #!/bin/bash +#----------------------------------------------------------------------------------------------------------------------------------- +# +# Music Folder Make +# +# Copyright (C) 2016-2026 Arnaud G. GIBERT +# mailto:arnaud@rx3.net +# +# This is free software: you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; If not, see +# . +# +#----------------------------------------------------------------------------------------------------------------------------------- + + +#----------------------------------------------------------------------------------------------------------------------------------- # Includes #----------------------------------------------------------------------------------------------------------------------------------- -. /usr/global/lib/music.bash +: "${RX3_LIB_DIR:=/usr/lib/rx3}" +. "${RX3_LIB_DIR}/music_tools.bash" -# System Constants +#----------------------------------------------------------------------------------------------------------------------------------- +# Global Variables #----------------------------------------------------------------------------------------------------------------------------------- - MFM_NAME="music_folder_make" -MFM_VERSION="$Name: music_mk_folder-1_0_0-1 $" +declare -g VERSION="1.0.0" +declare -g NAME="music_folder_make" +declare -g HELP="usage: [-h | --help] | [-V | --version] | [-T | --test] [-v | --verbose] [-p | --music_pattern ] [-r | --root_dir ]" + +declare -g ROOT_DIR="/opt/music/src" +declare -g MUSIC_PATTERN="/" + +declare -g MODE="DEFAULT" +declare -g VERBOSE="FALSE" +declare -g DRY_RUN="FALSE" -# Print Version +#----------------------------------------------------------------------------------------------------------------------------------- +# Version Print #----------------------------------------------------------------------------------------------------------------------------------- -function version_print() +mfm_version_print() { - echo ${MFM_VERSION} | sed -e 's/.*: //' -e 's/-/ /' -e 's/_/\./g' -e 's/\$$//' + version_print } -# Prin Help +#----------------------------------------------------------------------------------------------------------------------------------- +# Help Print #----------------------------------------------------------------------------------------------------------------------------------- -function help_print() +mfm_help_print() { - echo "${MFM_NAME} [-h | --help] | [-V | --version] | [-T | --test] [-v | --verbose] [-p | --music_pattern ] [-r | --root_dir ]" + mfm_version_print + help_print } +#----------------------------------------------------------------------------------------------------------------------------------- # Arg Parse #----------------------------------------------------------------------------------------------------------------------------------- -function args_parse() +mfm_args_parse() { - mode="default" - verbose="false" - root_dir="/opt/music/src" - music_pattern="/" - - tmp_args=$(getopt -o r:p:ThVv --long root_dir:,music_pattern:,test,help,version,verbose -n "${MFM_NAME}" -- "$@") + tmp_args=$(getopt -o r:p:ThVv --long root_dir:,music_pattern:,test,help,version,verbose -n "${NAME}" -- "$@") if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi # Note the quotes around `$TEMP': they are essential! eval set -- "${tmp_args}" - while true ; do + while true + do case "$1" in - # Path options - -r|--root_dir) shift; root_dir="$1"; shift;; - # Options - -p|--music_pattern) shift; music_pattern="$1"; shift;; + -r|--root_dir) shift; ROOT_DIR="$1"; shift;; + -p|--music_pattern) shift; MUSIC_PATTERN="$1"; shift;; # Mode switches - -T|--test) mode="test"; shift;; - -h|--help) mode="exit"; help_print; shift;; - -V|--version) mode="exit"; version_print; shift;; + -T|--test) MODE="TEST"; shift;; + -h|--help) MODE="EXIT"; mfm_help_print; shift;; + -V|--version) MODE="EXIT"; mfm_version_print; shift;; # Global options - -v|--verbose) verbose="true"; shift;; + -v|--verbose) VERBOSE="TRUE"; shift;; - # - --) shift; break;; - *) echo "args_parse internal error [$1] !"; exit 1;; + # End of options + --) shift; break;; + *) echo "args_parse internal error [$1] !"; exit 1;; esac done } @@ -87,72 +120,75 @@ function args_parse() +#----------------------------------------------------------------------------------------------------------------------------------- # Main #----------------------------------------------------------------------------------------------------------------------------------- -shopt -s extglob +mfm_args_parse "$@" -args_parse "$@" -if [[ ${mode} == "exit" ]] + +if [[ "${MODE}" == "EXIT" ]] then exit 0 else - if [[ ${mode} == "test" ]] + if [[ "${MODE}" == "TEST" ]] then - dry_run=true - else - dry_run=false + DRY_RUN="TRUE" fi fi -echo "mode: [${mode}] verbose: [${verbose}] root_dir: [${root_dir}] music_pattern: [${music_pattern}]" 1>&2 +echo_error "${NAME}: Mode: [${MODE}] Verbose: [${VERBOSE}] Root_Dir: [${ROOT_DIR}] Music_Pattern: [${MUSIC_PATTERN}]" -find ${root_dir} -type d -links 2 | grep -e "${music_pattern}" | grep -v -e "/video" -e "/photo" | sort | ( - while read dir - do - if [[ $(basename ${dir}) == "misc" ]] - then - line_echo "${dir}: Misc\r" "${i}" - else - - src="" - dst="${dir}/folder.jpg" +if [[ ! -d "${ROOT_DIR}" ]] +then + echo_error "Root directory doesn't exist !" + exit -1 +fi - for file in ${dir}/cover-front ${dir}/slipcase-front ${dir}/box-front - do +i=1 + +while read -r dir +do + if [[ "$(basename "${dir}")" == "misc" ]] + then + echo_line "${dir}: Misc\r" "${i}" + else + src="" + dst="${dir}/folder.jpg" + + for file in "${dir}/cover-front" "${dir}/slipcase-front" "${dir}/box-front" + do for suffix in png jpg do - if [[ "${src}" == "" ]] - then - if [[ -f "${file}.${suffix}" ]] - then - src="${file}.${suffix}" - fi - fi + if [[ "${src}" == "" ]] + then + if [[ -f "${file}.${suffix}" ]] + then + src="${file}.${suffix}" + fi + fi done - done + done - if [[ "${src}" == "" ]] - then - line_echo "${dir}: BAD!\n" "${i}" - else - if [[ ( -f "${dst}") && ( -s "${dst}") && ( "${dst}" -nt "${src}") ]] - then - line_echo "${dir}: Skipping\r" "${i}" - else - line_echo "${dir}: Processing...\n" "${i}" + if [[ "${src}" == "" ]] + then + echo_line "${dir}: BAD!\n" "${i}" + else + if [[ -f "${dst}" ]] && [[ -s "${dst}" ]] && [[ "${dst}" -nt "${src}" ]] + then + echo_line "${dir}: Skipping\r" "${i}" + else + echo_line "${dir}: Processing...\n" "${i}" + sh_exec "anytopnm \"${src}\" | pamscale -xyfit 1024 1024 | pnmtojpeg -quality=95 -optimize >\"${dst}\"" + fi + fi + fi - cmd="anytopnm \"${src}\" | pamscale -xyfit 1024 1024 | pnmtojpeg -quality=95 -optimize >\"${dst}\"" - exec_cmd "${cmd}" - fi - fi - fi + i=$(( i + 1 )) - i=$(($i + 1)) - done +done < <(find "${ROOT_DIR}" -type d -links 2 | grep -e "${MUSIC_PATTERN}" | grep -v -e "/video" -e "/photo" | sort) - line_echo "" -) +echo_line "" diff --git a/bin/music_tag_cleanner b/bin/music_tag_cleanner index 9da830e..efe1fbe 100755 --- a/bin/music_tag_cleanner +++ b/bin/music_tag_cleanner @@ -1,88 +1,121 @@ #!/bin/bash +#----------------------------------------------------------------------------------------------------------------------------------- +# +# Music Tag Cleaner +# +# Copyright (C) 2016-2026 Arnaud G. GIBERT +# mailto:arnaud@rx3.net +# +# This is free software: you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; If not, see +# . +# +#----------------------------------------------------------------------------------------------------------------------------------- + + +#----------------------------------------------------------------------------------------------------------------------------------- # Includes #----------------------------------------------------------------------------------------------------------------------------------- -. /usr/global/lib/music.bash +: "${RX3_LIB_DIR:=/usr/lib/rx3}" +. "${RX3_LIB_DIR}/music_tools.bash" -# System Constants +#----------------------------------------------------------------------------------------------------------------------------------- +# Global Variables #----------------------------------------------------------------------------------------------------------------------------------- - MTC_NAME="music_tag_cleaner" -MTC_VERSION="$Name: music_tag_cleaner-1_0_0-1 $" +declare -g VERSION="1.0.0" +declare -g NAME="music_tag_cleaner" +declare -g HELP="usage: [-h | --help] | [-V | --version] | [-T | --test] [-v | --verbose] [-f | --fix_missing_album_artist] [-a | --default_artist ] [-p | --music_pattern ] [-r | --root_dir ]" + +declare -g ROOT_DIR="/opt/music/src" +declare -g MUSIC_PATTERN="/" +declare -g DEFAULT_ARTIST="" +declare -g FIX_MAA="FALSE" + +declare -g MODE="DEFAULT" +declare -g VERBOSE="FALSE" +declare -g DRY_RUN="FALSE" -# Print Version +#----------------------------------------------------------------------------------------------------------------------------------- +# Version Print #----------------------------------------------------------------------------------------------------------------------------------- -function version_print() +mtc_version_print() { - echo ${MTC_VERSION} | sed -e 's/.*: //' -e 's/-/ /' -e 's/_/\./g' -e 's/\$$//' + version_print } -# Prin Help +#----------------------------------------------------------------------------------------------------------------------------------- +# Help Print #----------------------------------------------------------------------------------------------------------------------------------- -function help_print() +mtc_help_print() { - echo "${MTC_NAME} [-h | --help] | [-V | --version] | [-T | --test] [-v | --verbose] [-f | --fix_missing_album_artist] [-a | --default_artist ] [-p | --music_pattern ] [-r | --root_dir ]" + mtc_version_print + help_print } +#----------------------------------------------------------------------------------------------------------------------------------- # Arg Parse #----------------------------------------------------------------------------------------------------------------------------------- -function args_parse() +mtc_args_parse() { - mode="default" - verbose="false" - fix_maa="false" - default_artist="" - root_dir="/opt/music/src" - music_pattern="/" - - tmp_args=$(getopt -o r:p:a:ThVvf --long root_dir:,music_pattern:,default_artist,test,help,version,verbose,fix_missing_album_artist -n "${MTC_NAME}" -- "$@") + tmp_args=$(getopt -o r:p:a:ThVvf --long root_dir:,music_pattern:,default_artist:,test,help,version,verbose,fix_missing_album_artist -n "${NAME}" -- "$@") if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi # Note the quotes around `$TEMP': they are essential! eval set -- "${tmp_args}" - while true ; do + while true + do case "$1" in - # Path options - -r|--root_dir) shift; root_dir="$1"; shift;; - # Options - -a|--default_artist) shift; default_artist="$1"; shift;; - -p|--music_pattern) shift; music_pattern="$1"; shift;; + -r|--root_dir) shift; ROOT_DIR="$1"; shift;; + -p|--music_pattern) shift; MUSIC_PATTERN="$1"; shift;; + -a|--default_artist) shift; DEFAULT_ARTIST="$1"; shift;; # Mode switches - -T|--test) mode="test"; shift;; - -h|--help) mode="exit"; help_print; shift;; - -V|--version) mode="exit"; version_print; shift;; + -T|--test) MODE="TEST"; shift;; + -h|--help) MODE="EXIT"; mtc_help_print; shift;; + -V|--version) MODE="EXIT"; mtc_version_print; shift;; # Global options - -f|--fix_missing_album_artist) fix_maa="true"; shift;; - -v|--verbose) verbose="true"; shift;; + -f|--fix_missing_album_artist) FIX_MAA="TRUE"; shift;; + -v|--verbose) VERBOSE="TRUE"; shift;; - # - --) shift; break;; - *) echo "args_parse internal error [$1] !"; exit 1;; + # End of options + --) shift; break;; + *) echo "args_parse internal error [$1] !"; exit 1;; esac done } @@ -91,105 +124,111 @@ function args_parse() +#----------------------------------------------------------------------------------------------------------------------------------- # Main #----------------------------------------------------------------------------------------------------------------------------------- -shopt -s extglob +mtc_args_parse "$@" -args_parse "$@" -if [[ ${mode} == "exit" ]] + +if [[ "${MODE}" == "EXIT" ]] then exit 0 else - if [[ ${mode} == "test" ]] + if [[ "${MODE}" == "TEST" ]] then - dry_run=true - else - dry_run=false + DRY_RUN="TRUE" fi fi -echo "mode: [${mode}] verbose: [${verbose}] root_dir: [${root_dir}] music_pattern: [${music_pattern}] fix_maa: [${fix_maa}] default_artist: [${default_artist}]" 1>&2 +echo_error "${NAME}: Mode: [${MODE}] Verbose: [${VERBOSE}] Root_Dir: [${ROOT_DIR}] Music_Pattern: [${MUSIC_PATTERN}] Fix_MAA: [${FIX_MAA}] Default_Artist: [${DEFAULT_ARTIST}]" + +if [[ ! -d "${ROOT_DIR}" ]] +then + echo_error "Root directory doesn't exist !" + exit -1 +fi i=1 -find "${root_dir}" -name '*.flac' -o -name '*.mp3' | grep -e "${music_pattern}" | sort | - while read track_file +while read -r track_file +do + mt_tagtab_alloc + + mt_tagtab_read "0" "${track_file}" "DEFAULT" + + for tag in DISCTOTAL DISCNUMBER do - tagtab_alloc - - tagtab_read "0" "${track_file}" "DEFAULT" - - for tag in DISCTOTAL DISCNUMBER - do - if [[ "$(echo ${taglist} | grep -e ":${tag}:")" != "" ]] - then - line_echo "${track_file}: Cleaning '${tag}' Tag...\n" "${i}" - tag_delete "${track_file}" "${tag}" - fi - done - - if [[ "$(tag_exist "ALBUM ARTIST")" != "" ]] + if [[ "$(mt_tag_exist "${tag}")" != "" ]] then - if [[ "$(tag_exist "ALBUMARTIST")" == "" ]] + echo_line "${track_file}: Cleaning '${tag}' Tag...\n" "${i}" + mt_tag_delete "${track_file}" "${tag}" + fi + done + + if [[ "$(mt_tag_exist "ALBUM ARTIST")" != "" ]] + then + if [[ "$(mt_tag_exist "ALBUMARTIST")" == "" ]] + then + echo_line "${track_file}: Copying 'ALBUM ARTIST' into 'ALBUMARTIST' Tag...\n" "${i}" + mt_tag_write "${track_file}" "ALBUMARTIST" "${tagtab["0,ALBUM ARTIST"]}" + fi + + echo_line "${track_file}: Cleaning 'ALBUM ARTIST' Tag...\n" "${i}" + mt_tag_delete "${track_file}" "ALBUM ARTIST" + else + if [[ "$(mt_tag_exist "ALBUMARTIST")" == "" ]] + then + echo_line "${track_file}: Missing 'ALBUMARTIST' and 'ALBUM ARTIST' Tag...\n" "${i}" + + if [[ "${FIX_MAA}" == "TRUE" ]] then - line_echo "${track_file}: Copying 'ALBUM ARTIST' into 'ALBUMARTIST' Tag...\n" "${i}" - tag_write "${track_file}" "ALBUMARTIST" "${tagtab["0,ALBUM ARTIST"]}" - fi + artist="" - line_echo "${track_file}: Cleaning 'ALBUM ARTIST' Tag...\n" "${i}" - tag_delete "${track_file}" "ALBUM ARTIST" - else - if [[ "$(tag_exist "ALBUMARTIST")" == "" ]] - then - line_echo "${track_file}: Missing 'ALBUMARTIST' and 'ALBUM ARTIST' Tag...\n" "${i}" - - if [[ ( "${fix_maa}" == "true") ]] + if [[ "${DEFAULT_ARTIST}" != "" ]] then - if [[ "${default_artist}" != "" ]] - then - artist=${default_artist} - else - album_type=$(album_type_get "${track_file}") + artist="${DEFAULT_ARTIST}" + else + album_type=$(mt_album_type_get "${track_file}") - if [[ "/various_artists/tribute/original_soundtrack/child/" == */${album_type}/* ]] + if [[ "/various_artists/tribute/original_soundtrack/child/" == */${album_type}/* ]] + then + artist="Various Artists" + else + if [[ "$(mt_tag_exist "ARTIST")" == "" ]] then - artist="Various Artists" + echo_line "${track_file}: Warning: Missing 'ARTIST' Tag...\n" "${i}" else - if [[ "$(tag_exist "ARTIST")" == "" ]] - then - line_echo "${track_file}: Warning: Missing 'ARTIST' Tag...\n" "${i}" - else - artist="${tagtab["0,ARTIST"]}" - fi + artist="${tagtab["0,ARTIST"]}" fi fi + fi - if [[ "${artist}" != "" ]] - then - line_echo "${track_file}: Copying '${artist}' into 'ALBUMARTIST' Tag...\n" "${i}" - tag_write "${track_file}" "ALBUMARTIST" "${artist}" - fi + if [[ "${artist}" != "" ]] + then + echo_line "${track_file}: Copying '${artist}' into 'ALBUMARTIST' Tag...\n" "${i}" + mt_tag_write "${track_file}" "ALBUMARTIST" "${artist}" fi fi fi + fi - if [[ "${track_file##*.}" == "flac" ]] - then - if [[ "$(file ${track_file} | grep ID3 )" != "" ]] - then - line_echo "${track_file}: Cleaning Flac ID3 Tags...\n" "${i}" - tag_all_delete ${track_file} "id3" - fi + if [[ "${track_file##*.}" == "flac" ]] + then + if [[ "$(file "${track_file}" | grep ID3)" != "" ]] + then + echo_line "${track_file}: Cleaning Flac ID3 Tags...\n" "${i}" + mt_tag_all_delete "${track_file}" "id3" fi + fi - line_echo "${track_file}: OK\r" "${i}" + echo_line "${track_file}: OK\r" "${i}" - i=$(($i + 1)) - done + i=$(( i + 1 )) -line_echo "" +done < <(find "${ROOT_DIR}" \( -name '*.flac' -o -name '*.mp3' \) | grep -e "${MUSIC_PATTERN}" | sort) +echo_line "" diff --git a/etc/bash_completion.d/album_retitle b/etc/bash_completion.d/album_retitle new file mode 100644 index 0000000..170890d --- /dev/null +++ b/etc/bash_completion.d/album_retitle @@ -0,0 +1,95 @@ +#!/bin/bash +#----------------------------------------------------------------------------------------------------------------------------------- +# +# Album Retitle Bash Completion +# +# Copyright (C) 2016-2026 Arnaud G. GIBERT +# mailto:arnaud@rx3.net +# +# This is free software: you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; If not, see +# . +# +#----------------------------------------------------------------------------------------------------------------------------------- + + + +#----------------------------------------------------------------------------------------------------------------------------------- +# Album Retitle Completion +#----------------------------------------------------------------------------------------------------------------------------------- + +album_retitle_completion() +{ + local cur="${COMP_WORDS[COMP_CWORD]}" + local prev="${COMP_WORDS[COMP_CWORD-1]}" + local opts="-h --help -V --version -T --test -v --verbose" + + local pos=0 + local i + + COMPREPLY=() + + # Complete options if current word starts with '-' + if [[ "${cur}" == -* ]] + then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + + # Count non-option positional arguments already provided + for (( i=1; i. +# +#----------------------------------------------------------------------------------------------------------------------------------- + + + +#----------------------------------------------------------------------------------------------------------------------------------- +# _music_folder_make_completion +#----------------------------------------------------------------------------------------------------------------------------------- + +_music_folder_make_completion() +{ + local cur="${COMP_WORDS[COMP_CWORD]}" + local prev="${COMP_WORDS[COMP_CWORD-1]}" + local opts="-h --help -V --version -T --test -v --verbose -p --music_pattern -r --root_dir" + + COMPREPLY=() + + # Handle argument of options that take a value + case "${prev}" in + -r|--root_dir) + COMPREPLY=( $(compgen -d -- "${cur}") ) + return 0 + ;; + + -p|--music_pattern) + COMPREPLY=() + return 0 + ;; + esac + + # Complete options if current word starts with '-' + if [[ "${cur}" == -* ]] + then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + + return 0 +} + + + +complete -o filenames -F _music_folder_make_completion music_folder_make diff --git a/etc/bash_completion.d/music_info b/etc/bash_completion.d/music_info new file mode 100644 index 0000000..c9659a6 --- /dev/null +++ b/etc/bash_completion.d/music_info @@ -0,0 +1,59 @@ +#!/bin/bash +#----------------------------------------------------------------------------------------------------------------------------------- +# +# Music Info Bash Completion +# +# Copyright (C) 2016-2026 Arnaud G. GIBERT +# mailto:arnaud@rx3.net +# +# This is free software: you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; If not, see +# . +# +#----------------------------------------------------------------------------------------------------------------------------------- + + + +#----------------------------------------------------------------------------------------------------------------------------------- +# _music_info_completion +#----------------------------------------------------------------------------------------------------------------------------------- + +_music_info_completion() +{ + local cur="${COMP_WORDS[COMP_CWORD]}" + local prev="${COMP_WORDS[COMP_CWORD-1]}" + local opts="-h --help -V --version -v --verbose -l --list -r --root_dir" + + COMPREPLY=() + + # Handle argument of options that take a value + case "${prev}" in + -r|--root_dir) + COMPREPLY=( $(compgen -d -- "${cur}") ) + return 0 + ;; + esac + + # Complete options if current word starts with '-' + if [[ "${cur}" == -* ]] + then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + + return 0 +} + + + +complete -o filenames -F _music_info_completion music_info diff --git a/etc/bash_completion.d/music_tag_cleaner b/etc/bash_completion.d/music_tag_cleaner new file mode 100644 index 0000000..f94e70f --- /dev/null +++ b/etc/bash_completion.d/music_tag_cleaner @@ -0,0 +1,71 @@ +#!/bin/bash +#----------------------------------------------------------------------------------------------------------------------------------- +# +# Music Tag Cleaner Bash Completion +# +# Copyright (C) 2016-2026 Arnaud G. GIBERT +# mailto:arnaud@rx3.net +# +# This is free software: you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; If not, see +# . +# +#----------------------------------------------------------------------------------------------------------------------------------- + + + +#----------------------------------------------------------------------------------------------------------------------------------- +# _music_tag_cleaner_completion +#----------------------------------------------------------------------------------------------------------------------------------- + +_music_tag_cleaner_completion() +{ + local cur="${COMP_WORDS[COMP_CWORD]}" + local prev="${COMP_WORDS[COMP_CWORD-1]}" + local opts="-h --help -V --version -T --test -v --verbose -f --fix_missing_album_artist -a --default_artist -p --music_pattern -r --root_dir" + + local i + + COMPREPLY=() + + # Handle argument of options that take a value + case "${prev}" in + -a|--default_artist) + COMPREPLY=() + return 0 + ;; + + -p|--music_pattern) + COMPREPLY=() + return 0 + ;; + + -r|--root_dir) + COMPREPLY=( $(compgen -d -- "${cur}") ) + return 0 + ;; + esac + + # Complete options if current word starts with '-' + if [[ "${cur}" == -* ]] + then + COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) + return 0 + fi + + return 0 +} + + + +complete -o filenames -F _music_tag_cleaner_completion music_tag_cleaner