Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Reduce the number of folders taken by a music collection to please some car head units
#!/usr/bin/env bash
#
# Some car head units have restrictions on the number of folders they can access,
# this scripts aims to reduce the number of folders taken by a music collection.
# Assumes the music collection is set up as Artist / Album
# This also ensures the folders and files don't exceed the maximum file size.
# My own head unit restrictions: 255 folders, folder/filename size: 63 chars
export MAX_FILE_SIZE=63
export APPLY_CHANGES=false
# flatten dir by concatenating parent dir name with dir name
flatten_dir() {
dir=$1
new_dir=`sed 's/\(.*\)\//\1_/' <<< "$dir"`
echo "mv \"$dir\" \"$new_dir\""
if [ "$APPLY_CHANGES" = true ] ; then
mv "$dir" "$new_dir"
fi
}
export -f flatten_dir
# if artist folder has single album plus loose mp3s, move the mp3s to album folder
move_mp3_to_subdir() {
dir=$1
subdirs_count=`find "$dir" -depth 1 -type d | wc -l | tr -d "[:blank:]"`
if [ "$subdirs_count" -ne 1 ]; then
return 0
fi
subdir=`find "$dir" -type d -depth 1 -print -quit`
if [ "$APPLY_CHANGES" = true ] ; then
find "$dir" -iname '*.mp3' -depth 1 -print -exec mv "{}" "$subdir" \;
else
find "$dir" -iname '*.mp3' -depth 1 -exec echo "mv \"{}\" \"$subdir\"" \;
fi
}
export -f move_mp3_to_subdir
shorten_name() {
name=$1
name_size=`wc -c <<< "$name" | tr -d "[:blank:]"`
if [ "$name_size" -le "$MAX_FILE_SIZE" ]; then
return 0
fi
ext=${name#"${name%.[^\ ]*}"}
echo "[$name_size] mv \"$name\" \"${name:0:MAX_FILE_SIZE-1-${#ext}}${ext}\""
if [ "$APPLY_CHANGES" = true ] ; then
mv "$name" "${name:0:MAX_FILE_SIZE-1-${#ext}}${ext}"
fi
}
export -f shorten_name
# for mp3s in CD/Disk folder inside album, move them above to the album folder
rename_mp3_and_move_above() {
dir=$1
disk_number=`basename "$dir" | tr -dc '0-9'`
disk_int=`expr $disk_number + 0`
if ((disk_int < 1 || disk_int > 99)); then
return 0
fi
if [ "$APPLY_CHANGES" = true ] ; then
find "$dir" -iname '*.mp3' -depth 1 -print -execdir mv "{}" "../$disk_number{}" \;
else
find "$dir" -iname '*.mp3' -depth 1 -execdir echo "mv \"{}\" \"../$disk_number{}\"" \;
fi
}
export -f rename_mp3_and_move_above
execute_operations() {
echo
echo "Delete non mp3/wma files:"
if [ "$APPLY_CHANGES" = true ] ; then
find . -type f -not -iname '*.mp3' -not -iname '*.wma' -not -path '*/\.*' -print -delete
else
find . -type f -not -iname '*.mp3' -not -iname '*.wma' -not -path '*/\.*' -print
fi
echo
echo "Move loose mp3s to subdirectories:"
find . -type d -depth 1 -exec bash -c 'move_mp3_to_subdir "$1"' _ {} \;
echo
echo "Move mp3s in CD/Disk folder to album folder:"
find . -type d -depth 3 -regex '.*[^/]*[0-9][^/]*' -exec bash -c 'rename_mp3_and_move_above "$1"' _ {} \;
echo
echo "Flatten Directories:"
find ~+ -type d -depth 2 -exec bash -c 'flatten_dir "$1"' _ {} \;
echo
echo "Shorten filenames:"
find . -not -path '*/\.*' -regex ".*[^/]\{$MAX_FILE_SIZE,\}" -execdir bash -c 'shorten_name "$1"' _ {} \;
echo
echo "Delete empty folders:"
if [ "$APPLY_CHANGES" = true ] ; then
find . -type d -empty -print -exec rmdir "{}" \;
else
find . -type d -empty -print
fi
}
echo "Working dir: $PWD"
echo
echo "Total dirs before changes: `find . -type d | wc -l | tr -d "[:blank:]"`"
echo
echo "Calculating changes:"
execute_operations
read -p "Apply the above changes? [Y/n]" -n 1 -r
echo
if [[ ! $REPLY =~ ^[Y]$ ]]; then
exit 0
fi
export APPLY_CHANGES=true
execute_operations
echo
echo "Total dirs after changes: `find . -type d | wc -l | tr -d "[:blank:]"`"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment