diff options
Diffstat (limited to 'unix/id3tag.sh')
-rwxr-xr-x | unix/id3tag.sh | 513 |
1 files changed, 513 insertions, 0 deletions
diff --git a/unix/id3tag.sh b/unix/id3tag.sh new file mode 100755 index 0000000..93cd099 --- /dev/null +++ b/unix/id3tag.sh @@ -0,0 +1,513 @@ +#!/bin/sh +# +# MP3 id3tag functions +# +# Copyright (C) 2005 Robert, Zhang Le +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +# INTRO: +# This file contains several functions related to mp3 file's operations. +# I wrote them in order to ease the process of transforming the encoding +# of mp3 file's id3tag from gbk to utf8. YOU NEED id3v2 to make these +# functions work. +# !!! USE THESE FUNCTIONS IN UTF-8 LOCALE !!! + +# TODO: +# 1. make all the functions work both on a directory and a file +# 2. add testing feature to all functions +# * rename_delete_ending_artist() +# * check_artist() +# 3. set_artist() maybe need to be improved +# 4. if functions are called without params, echo "usage" + +# USAGE: +# 1. source this file before use + + +# get_title_1() can be used to get v1 title from an mp3 file's id3tag +# get_title_1_convernted() convert its encoding from gbk to utf8 + +get_title_1(){ + id3v2 -l "$1" | grep ^Title \ + | sed -e 's/^Title : //g' -e 's/[[:space:]]*Artist: [[:print:]]*//g' +} +get_title_1_converted(){ + id3v2 -l "$1" | grep ^Title \ + | sed -e 's/^Title : //g' -e 's/[[:space:]]*Artist: [[:print:]]*//g' \ + | iconv -f gbk -t utf8 +} + +# ATTENTION: if title encoding is gbk, the following function does not +# function ideally, because "." can't match invisible/unmappd char? +get_artist_1(){ + id3v2 -l "$1" | grep ^Title \ + | sed -e 's/^Title.*Artist: //g' +} + +get_title_2(){ + id3v2 -l "$1" | grep ^TIT2 | tail -n 1 | sed -e 's/^.*: //g' +} +get_title_2_converted(){ + id3v2 -l "$1" | grep ^TIT2 | tail -n 1 | sed -e 's/^.*: //g' \ + | iconv -f gbk -t utf8 + +} +get_artist_2(){ + id3v2 -l "$1" | grep ^TPE1 | tail -n 1 | sed -e 's/^.*: //g' +} + + +# if only one param, it must be a dirname, and at the same time an artist's name +# if two param, the first artist name, the second dirname +set_artist(){ + local artist + + if [[ $# -eq 0 ]]; then + echo "set_artist artist [dir]" + return; + else + artist="$1"; + fi + + if [[ $# -eq 2 ]]; then + if [[ -d $2 ]]; then + shift; + else + echo "the 2nd param must be a dir" + return; + fi + elif [[ $# -eq 1 ]]; then + if [[ ! -d $1 ]]; then + echo "the sole param must be also a dir" + return; + fi + fi + + find "$1" -name "*.mp3" -print0 | xargs -0 id3v2 -a "$artist" ; + +} + +id3_convert_set_title(){ + local target + local title + local testing + local tmp + local i + + if [[ $# -eq 0 ]]; then + echo "needs parameters" + return; + fi + + if [[ $1 == "notest" ]]; then + testing=0; + shift; + else + testing=1; + fi + + + while [[ $# -gt 0 ]]; do + if [[ -d "$1" ]]; then + for i in "$1"/*.mp3; + do + title=`get_title_1_converted "$i"` + + # if the last command, ie. iconv fails + # then probably the file's id3tag has already been converted + if [[ $? -ne 0 ]]; then + continue; + fi + + tmp=`echo -n "$title" | sed -e 's/Track//g' -e 's/[[:space:][:digit:]]*//g'` + + if [[ -z $tmp ]]; then + title=`get_title_2_converted "$i"` + + if [[ $? -ne 0 ]]; then + continue; + fi + + tmp=`echo -n "$title" | sed -e 's/Track//g' -e 's/[[:space:][:digit:]]*//g'` + + if [[ -z $tmp ]]; then + echo "title is "$tmp" nothing need to be done" + continue; + fi + fi + + if [[ -n $title ]]; then + if [[ $testing -eq 1 ]]; then + echo $title; + else + echo -n $title; + id3v2 -1 -t "$title" "$i"; + id3v2 -2 -t "$title" "$i"; + echo " done"; + fi + fi + done + elif [[ -f "$1" ]]; then + title=`get_title_1_converted "$1"` + if [[ $? -ne 0 ]]; then + shift; + continue; + fi + + tmp=`echo -n "$title" | sed -e 's/Track//g' -e 's/[[:space:][:digit:]]*//g'` + + if [[ -z $tmp ]]; then + title=`get_title_2_converted "$1"` + + if [[ $? -ne 0 ]]; then + continue; + fi + + tmp=`echo -n "$title" | sed -e 's/Track//g' -e 's/[[:space:][:digit:]]*//g'` + + if [[ -z $tmp ]]; then + echo "title is "$tmp" nothing need to be done" + shift; + continue; + fi + fi + + if [[ -n $title ]]; then + if [[ $testing -eq 1 ]]; then + echo $title; + else + echo -n $title; + id3v2 -1 -t "$title" "$1"; + id3v2 -2 -t "$title" "$1"; + echo " done"; + fi + fi + fi + shift; + done + + if [[ $testing -eq 1 ]]; then + echo "testing finished, to convert use \"notest\" as the fist param" + fi +} + +# make sure file name ends with ".mp3" +id3_set_title_as_filename(){ + local title + local testing + local i + + if [[ $# -eq 0 ]]; then + echo "needs parameters"; + return; + fi + + if [[ $1 == "notest" ]]; then + testing=0; + shift; + else + testing=1; + fi + + while [[ $# -gt 0 ]]; do + if [[ -d "$1" ]]; then + for i in "$1"/*.mp3; do + title=`basename "$i" | sed -e 's/\.mp3//g'` + if [[ $testing -eq 1 ]]; then + echo $title; + else + echo -n $title; + id3v2 -1 -t "${title}" "$i"; + id3v2 -2 -t "${title}" "$i"; + echo " done"; + fi + done + elif [[ -f "$1" ]]; then + title=`basename "$1" | sed -e 's/\.mp3//g'` + if [[ $testing -eq 1 ]]; then + echo $title; + else + echo -n $title; + id3v2 -1 -t "$title" "$1"; + id3v2 -2 -t "$title" "$1"; + echo " done"; + fi + fi + shift; + done + + if [[ $testing -eq 1 ]]; then + echo "testing finished, to convert use \"notest\" as the fist param" + fi +} + +id3_rename_MP3_to_mp3(){ + local target + local i + + if [[ $# -eq 0 ]]; then + echo "needs parameters"; + return; + fi + + while [[ $# -gt 0 ]]; do + if [[ -d "$1" ]]; then + for i in "$1"/*.MP3; do + target="$1"/`basename "$i" | sed -e 's/MP3$/mp3/g'` + if [[ "$i" != "$target" ]]; then + mv "$i" "$target"; + echo "$i -> $target: done" + fi + done + elif [[ -f "$1" ]]; then + target=`dirname "$1"`/`basename "$1" | sed -e 's/MP3$/mp3/g'` + if [[ "$1" != "$target" ]]; then + mv "$1" "$target"; + echo "$1 -> $target: done" + fi + fi + shift; + done +} + +# use this function to remove leading garbages in the file name +# Sometimes, the file name in the form of "artist -(1). title.mp3" +# we just need title.mp3 +# the delim is the adjacent char before "title" + +id3_rename_delete_leading_garbage(){ + local target + local testing + local orig="^0[0-9]\." + #local orig="^[[:alnum:]]*[-.()[:digit:][:space:]]*" + local delim="[[:space:]]" + # ATTENTION: if delimeter is ".", delim should be "\." + # when passing on command line, it should be "\\\." + local new="" + local i + + if [[ $# -eq 0 ]]; then + echo "needs parameters"; + return; + fi + + if [[ $1 == "notest" ]]; then + testing=0; + shift; + else + testing=1; + fi + + if [[ "${1/=*/}" == "delim" ]]; then + delim="${1/*=/}"; + echo $delim; + shift; + fi + + while [[ $# -gt 0 ]]; do + if [[ -d "$1" ]]; then + echo $1 + for i in "$1"/*.mp3; do + target="$1"/`basename "$i" | sed -e "s/$orig$delim/$new/g"` + if [[ "$i" != "$target" ]]; then + echo -n "$target"; + if [[ $testing -eq 0 ]]; then + mv "$i" "$target"; + fi + echo " done" + else + echo "$target"; + fi + done + elif [[ -f "$1" ]]; then + target=`dirname "$1"`/`basename "$1" | sed -e "s/$orig$delim/$new/g"` + if [[ "$1" != "$target" ]]; then + echo -n "$target"; + if [[ $testing -eq 0 ]]; then + mv "$1" "$target"; + fi + echo " done"; + else + echo $target; + fi + fi + shift; + done + + if [[ $testing -eq 1 ]]; then + echo "testing finished, to convert use \"notest\" as the fist param" + fi +} + +# use this function after conversion +id3_rename_as_title(){ + local target + local title + local testing + local i + + if [[ $# -eq 0 ]]; then + echo "needs parameters"; + return; + fi + + if [[ $1 == "notest" ]]; then + testing=0; + shift; + else + testing=1; + fi + + while [[ $# -gt 0 ]]; do + if [[ -d "$1" ]]; then + for i in "$1"/*.mp3; do + title=`get_title_1 "$(basename $i)"` + + # if the last command, ie. iconv fails + # then probably the file's id3tag has already been converted + if [[ $? -ne 0 ]]; then + continue; + fi + + title=`echo -n "$title" | sed -e 's/[[:space:][:punct:]]*//g'` + + if [[ -z $title ]]; then + title=`get_title_2_converted "$(basename $i)"` + if [[ $? -ne 0 ]]; then + continue; + fi + fi + + target="$1"/`get_title_2 "$i"`.mp3 + + if [[ -a "$target" ]]; then + echo "$target exists, skiping" + continue; + fi + + if [[ "$i" != "$target" ]] ; then + if [[ $testing -eq 0 ]]; then + mv "$i" "$target"; + fi + echo "$i -> $target: done"; + fi + done + elif [[ -f "$1" ]]; then + target=`dirname "$1"`/`get_title_2 "$1"`.mp3 + + if [[ -a "$target" ]]; then + echo "$target exists, skiping" + shift; + continue; + fi + + if [[ "$1" != "$target" ]]; then + if [[ $testing -eq 0 ]]; then + mv "$1" "$target"; + fi + echo "$1 -> $target: done"; + fi + fi + shift; + done + + if [[ $testing -eq 1 ]]; then + echo "testing finished, to convert use \"notest\" as the fist param" + fi +} + +id3_check_title(){ + local target + local i + local title1 + local title2 + + if [[ $# -eq 0 ]]; then + echo "needs parameters"; + return; + fi + + while [[ $# -gt 0 ]]; do + if [[ -d "$1" ]]; then + echo $1 + for i in "$1"/*.mp3 + do + title1=`get_title_1 "$i"`; + title2=`get_title_2 "$i"`; + printf "%s \tv1: %s \tv2: %s\n" "$i" "$title1" "$title2"; + done + elif [[ -f "$1" ]]; then + title1=`get_title_1 "$1"`; + title2=`get_title_2 "$1"`; + printf "%s \tv1: %s \tv2: %s\n" "$1" "$title1" "$title2"; + + fi + shift; + done +} + +id3_check_title_converted(){ + local target + local i + local title1 + local title2 + + if [[ $# -eq 0 ]]; then + echo "needs parameters"; + return; + fi + + while [[ $# -gt 0 ]]; do + if [[ -d "$1" ]]; then + echo $1 + for i in "$1"/*.mp3 + do + title1=`get_title_1_converted "$i"`; + title2=`get_title_2_converted "$i"`; + printf "%s \tv1: %s \tv2: %s\n" "$i" "$title1" "$title2"; + done + elif [[ -f "$1" ]]; then + title1=`get_title_1_converted "$1"`; + title2=`get_title_2_converted "$1"`; + printf "%s \tv1: %s \tv2: %s\n" "$1" "$title1" "$title2"; + + fi + shift; + done +} + +id3_check_artist(){ + for i in *.mp3; + do + artist1=`get_artist_1 "$i"`; + artist2=`get_artist_2 "$i"`; + printf "%s \tv1: %s \tv2: %s\n" "$i" "$artist1" "$artist2"; + done +} +# if filename ends with "_artist", use this one to remove the suffix +id3_rename_delete_ending_artist(){ + + if [[ $# -eq 0 ]]; then + echo "needs parameters"; + return; + fi + + for i in "$1"/*.mp3; do + mv "$i" "${i/_*./.}"; + done +} + |