#!/bin/bash

# Replaces odd characters in filenames and directories with an underline
# When there are more consecutive odd characters what would result in ____ sth like this, it collates to a single underline.
# When the new unixified filename is already taken, a counted suffix will be added before an eventuel period in the filename, otherwise just append.
# Will never overwrite a file.

# usage: unixify.sh path [--doit]
# path  The file to unixify, can be file or folder.

export IFS=$'\n'
rootdir=$1
really_do_it=$2

function usage {
    echo "usage: unixify.sh path [--doit]"
    echo ""
    echo "  path - The file to unixify, can be file or folder"
    echo "  --doit - dry run unless specified"
    echo ""
    echo "Replaces odd characters in filenames and directories with an underline"
    echo "When the new unixified filename is already taken, a counted suffix will be"
    echo "added before an eventual dot in the filename, otherwise just appended."
    echo "Will never overwrite a file."
    exit 255
}

function unixify_string {
    local retval=$(echo $1 | gsed -e 's/[^A-Za-z0-9#./_-]/_/g') # replace everything else with _
    retval=$(echo $retval | gsed -e 's/\.\{2,\}/\./g')          # replace >1 consecutive . with one .
    retval=$(echo $retval | gsed -e 's/_\{2,\}/_/g')            # replace >1 consecutive _ with one _
    echo $retval
}

function unixify_filename {
    fname_full=$1
    current_dir=$(dirname $fname_full)
    current_file=$(basename $fname_full)
    fname_new=$(unixify_string $current_file) # unixify

    #echo "$fname_full"
    if [ "$current_file" != "$fname_new" ]; then { #any changes been needed?
        count=1
        while [ -e $current_dir/$fname_new ]; do { #new filename already taken?
            #echo file exists: $current_dir/$fname_new;

            #add suffix before any dot, if no dot just append
            if [[ "$fname_new" =~ \. ]]; then {
                fname_new=$(echo $fname_new | sed -e "s/\./_$count\./g")
            }; else {
                fname_new=$fname_new"_$count"
            }; fi

            count=$(($count + 1))
        }; done

        cmd="mv '$fname_full' '$current_dir/$fname_new'"

        echo $cmd
        if [ "$really_do_it" == "--doit" ]; then {
            eval $cmd
        }; fi
    }; fi
}

function unixify_path_contents {
    fpath=$1
    for i in $(find $fpath -mindepth 1 -maxdepth 1 | sort); do {
        unixify_filename $i;
    }; done
    for i in $(find $fpath -mindepth 1 -maxdepth 1 -type d | sort); do {
        unixify_path_contents $i;
    }; done
}

if [ -z "$rootdir" ]; then {
    usage
}; fi

if [ ! -e $rootdir ]; then {
    echo "$rootdir - no such file or dir"
    exit 255
}; fi

if [ "$really_do_it" != "--doit" ]; then {
    echo "Dry run. Not really doing anything."
}; fi

unixify_path_contents $rootdir