script=`basename "$0"`
version='1.0.1'
E_MISSING=64 E_BADARGS=65 E_BADDIR=66
case "`uname`" in
CYGWIN*)
under_cygwin=1
CYGWIN=${CYGWIN:-tty notitle glob nontsec}
CYGWIN+=" winsymlinks";;
*) under_cygwin=0;;
esac
function Panic {
cat <<EOF >&2
Panic! in shell $$, pipe $?, terminal `tty`: $*
$script exits with -1
EOF
exit -1
}
function Ok {
[ -z "$*" ] || echo "$*"; exit 0
}
function CroakArgs {
Usage; exit $E_BADARGS
}
function CroakUnlessGnuFind {
if ((!$have_gnu_find)); then
echo "CAUTION: GNU find required" >&2
exit $E_NOTGNU
fi
}
function Version {
cat <<EOF >&2
$script version $version
EOF
}
function Usage {
Version; cat <<EOF >&2
Usage:
$script [-o OUTDIR] [-n] [-r] [DIRNAME | FLACFILE]
$script [-h | -V]
EOF
}
function Help {
Usage; cat <<EOF >&2
Description:
Convert FLAC to high-quality MP3 files. When no input directory or file name is
specified converts all .flac-files in current directory.
This portable shell script should work on any UNIX and Windows (Cygwin) system.
Simply copy it into your path (e.g. to "/usr/local/bin" or "~/bin"). Maintained
at <http://www.visualco.de>.
Options:
-p, -p N Start N parallel conversion jobs (default: $optmaxprocs).
-o DIR Output directory for MP3 files. Default is to write each MP3 along
with its source FLAC.
-r Find FLAC recursively.
-V Print version information.
-h, -H Print this information.
Prerequisites:
bash, flac, metaflac, lame, id3
Exit codes:
0 Indicates success to the shell.
-1 Indicates an unexpected error.
$E_MISSING Missing programs
$E_BADARGS Bad command-line arguments.
$E_BADDIR Invalid directory.
EOF
}
optrecurse=0 optmaxprocs=2 optdry=0 optin= optout=
optmetacmd=id3
while getopts 'nro:P:hHV' opt; do
case $opt in
P) optmaxprocs=$OPTARG;;
r) optrecurse=1;;
n) optdry=1;;
o) optout="$OPTARG";;
P) optmaxprocs=$OPTARG;;
V) Version; Ok;;
[hH]) Help; Ok;;
*) CroakArgs;;
esac
done
shift $(($OPTIND - 1))
optin=${1:-.}
if [ -d "$optin" ]; then
[ -z "$2" ] || {
echo "Only one search directory allowed" >&2
exit $E_BADDIR
}
elif [ -f "$optin" ]; then
((!$optrecurse)) || CroakArgs
else
echo "$optin: directory not found" >&2
exit $E_BADDIR
fi
find=`which find`
if ((!$under_cygwin)); then
res=`$find --version`
if [ "$?" -ne "0" ]; then
cat <<EOF >&2
CAUTION: Find is '$find', the Microsoft 'find' utility. Possibly the
Cygwin-bin-directory does not come first in PATH (see "~/.bash_login"
and "/etc/profile").
EOF
find=/usr/bin/find res=`$find --version`
if [ "$?" -ne "0" ]; then
Panic "'$find' not found"
else
cat <<EOF >&2
WARNING: Using '$find' explicitly.
EOF
fi
fi
fi
res=`$find -regextype posix-egrep 2>&1 &>/dev/null`
if [ "$?" -ne "0" ]; then cat <<EOF >&2;
WARNING: '$find' does not understand '-regextype'.
EOF
have_gnu_find=0
else
have_gnu_find=1
fi
if [[ -d "$optin" ]]
then
for prog in flac lame id3 metaflac
do
which "$prog" >/dev/null || {
echo "'$prog' program not found" >&2
exit $E_MISSING
}
done
declare -a findopts
(($optrecurse)) || findopts=(-maxdepth 1)
ouropts=() i=0
[ -n "$optout" ] && {
ouropts[$((i++))]="-o"
ouropts[$((i++))]="$optout"
}
(($optdry)) && ouropts[$((i++))]="-n"
$find "$optin" "${findopts[@]}" -iname '*.flac' -print0 | {
xargs -0 -P $optmaxprocs -I{} "$0" "${ouropts[@]}" "{}"
}
else
declare base="${optin%%.flac}"
declare flacfile="${optin}" mp3file="${base}.mp3"
declare -a lameopts=(-V 0 --vbr-new -q 1 -m j)
declare -a flacopts=(--silent)
[ -n "${optout}" ] && mp3file="${optout}/$(basename "${mp3file}")"
cat <<EOF
Converting:
$flacfile
EOF
(($optdry)) || {
flac -d -c "${flacopts[@]}" "$flacfile" |
lame "${lameopts[@]}" - "$mp3file"
}
case "$optmetacmd" in
id3)
for tag in ARTIST TITLE ALBUM GENRE TRACKNUMBER DATE COMMENT
do
x="$(metaflac "$flacfile" --show-tag=$tag | sed s/.*=//g)"
eval $tag=\"$x\"
done
cat <<EOF
Copying ID3 tags
$ARTIST
$ALBUM ($DATE)
$TITLE
$GENRE
to
$mp3file
EOF
(($optdry)) || {
id3 -t "$TITLE" -T "${TRACKNUMBER:-0}" \
-a "$ARTIST" -A "$ALBUM" -y "$DATE" -g "${GENRE:-12}" \
-c "$COMMENT" \
"$mp3file"
}
;;
esac
fi
Ok