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