I own a music collection of a lot of mp3 files, some wma and m4a too, and interested in converting it all to ogg, I programed the following script...
The purpose is to maintain the structure of my collection, which is based on directories, classified by genre, artist and album names. I wasn't interested in converting ALL of my collection, but only specific directories, so here it comes:
audiomedia2ogg.shsyntax: audiomedia2ogg.sh dest_dir
It begins at current working directory and loops through all its subdirectories, searching for media files with .mp3, .wma or .m4a suffixes.
Internally it uses a second argument, but I really don't use it... I just navigate to the parent directory of the files I want to convert in my collection and call the script, specifying the directory in which the converted collection should be built.
You need to have
mplayer (just for wma files) and
sox with mp3 (and m4a too) support installed for this to work. Instead of
sox, you may use
oggenc or another similar program...
Code:
#!/bin/bash
echo $2;
currdir=`pwd`;
currdirname=`basename "$currdir"`;
#builds destination structure
if [ ! -d "$1"/"$currdirname" ]; then
cd "$1"/"$2"
mkdir "$currdirname"
res=$?;
if [ $res -eq 1 ]; then
exit
fi
fi
cd "$currdir";
echo "MP3 Files";
countfiles=`ls -l *.mp3 | wc -l`;
if [ $countfiles -ne 0 ]; then
for f in *.mp3; do
echo "file $f";
sox -t mp3 "$f" "$1"/"$2""$currdirname"/"`basename "$f" .mp3`.ogg";
done;
fi
echo "M4A Files";
countfiles=`ls -l *.m4a | wc -l`;
if [ $countfiles -ne 0 ]; then
for f in *.m4a; do
echo "file $f";
sox -t m4a "$f" "$1"/"$2""$currdirname"/"`basename "$f" .m4a`.ogg";
done;
fi
echo "WMA Files"
countfiles=`ls -l *.wma | wc -l`;
if [ $countfiles -ne 0 ]; then
for f in *.wma; do
echo "file $f";
mplayer -really-quiet -slave -nolirc -vc null -vo null -ao pcm:file=/tmp/"`basename "$f" .wma`.wav" "$f";
sox -t wav /tmp/"`basename "$f" .wma`.wav" "$1"/"$2""$currdirname"/"`basename "$f" .wma`.ogg";
rm /tmp/"`basename "$f" .wma`.wav";
done;
fi
#loops direct subdirectories
#don't want to account spaces when finding subdirectory names, because some subdirectories may have spaces in their names
SAVEIFS=$IFS
IFS=$(echo -en "\n\b")
for d in $(find . -type d); do
#except for current '.' directory
if [ "$d" != "." -a "`basename "$d"`" != "$currdirname" ]; then
echo "";
echo "to dir ""`basename "$d"`";
cd "$currdir"/"`basename "$d"`";
res=$?;
if [ $res -eq 0 ]; then
"$0" "$1" "$2""$currdirname"/
fi
fi
done;
IFS=$SAVEIFS
Some points to consider:
-The script still gives some error messages, about nonexistent subdirectories, and warning messages for ls when current directory doesn't has any files with the supported extensions. But besides that little bug, it still works fine! my collection is ported into ogg format with no problems (except for possible problems with the programs I use for the conversions)
-The script may (or should!) be expanded, so if I already have ogg files in my collection, they should be copied verbatim to the destination
-I use (or may be abuse) a lot of "" for the file and directory names, so names with spaces wouldn't matter...
-The script is recursive, as can be seen with the $0. Unless you have a lot of nested subdirectories, I don't think the memory stack would be a problem...
-Of course, if you add an '&' at the end of the recursive call, memory will be an issue because the for loop will try to go through all the direct subdirectories of current parent directory at the same time, and on and on and on... so a complex structured collection will give BIG problems...