#!/bin/sh # Program: # * rename file while removing [:punct:], replace [:upper:] with # [:lower:], replace "${sep}" with '_' # * while given '-d' , do not rename file, only print new # file name # Dependency: # * err.sh # Author: # * Chang, Chu-Kuan # # Setting # # Characters which will be replaced by '_', other [:punct:] not presented here # will be deleted readonly sep='[]()._-[:blank:]' . err.sh help_msg() { cat << EOF Usage: ${progname} [-hd] file... - format filename Options: -d Perform a 'dry run'. Do not actually rename file. -h Show this message and exit. EOF } process_file() { file="$1" dir="$(dirname "${file}")" base="$(basename "${file}")" # Return if there is error parsing file name if test -z "${file}" || test -z "${dir}" || test -z "${base}"; then printf '%s: error parsing file: %s\n' "${progname}" "${file}" 1>&2 return 1 fi case "${base}" in # file name with extension *.*) # get file extension extension="${base##*.}" # process file name new_base="$(printf '%s' "${base%.*}" \ | iconv --to-code=utf-8 \ | tr "${sep}" ' ' \ | tr -d '[:punct:]' \ | tr '[:upper:]' '[:lower:]' \ | tr -s ' ' '_' \ | sed 's/^_//; s/_$//' ).${extension}" ;; # file name without extension *) new_base="$(printf '%s' "${base}" \ | iconv --to-code=utf-8 \ | tr "${sep}" ' ' \ | tr -d '[:punct:]' \ | tr '[:upper:]' '[:lower:]' \ | tr -s ' ' '_' \ | sed 's/^_//; s/_$//' )" ;; esac if test "${base}" = "${new_base}"; then clean_file_cnt="$((clean_file_cnt + 1))" printf '%s: file %s require no rename\n' "${progname}" \ "${base}" return 0 fi case "${d_flag}" in '1') # While given '-d', do not rename file, only # print new file name printf '%s -> %s\n' "${base}" "${new_base}" ;; *) # Rename file (prompt before overwrite) mv -iv "${dir}/${base}" "${dir}/${new_base}" \ && success_file_cnt="$((success_file_cnt + 1))" ;; esac } readonly progname="$(basename "$0")" d_flag='0' total_file_cnt='0' success_file_cnt='0' clean_file_cnt='0' while getopts 'dh' opt; do case "${opt}" in 'd') readonly d_flag='1' ;; 'h') help_msg exit 0 ;; *) err '1' 'invalid option\n' ;; esac done shift "$((OPTIND - 1))" for arg; do total_file_cnt="$((total_file_cnt + 1))" process_file "${arg}" done # Report status printf '\n%s: renamed %d, clean %d, total %d/%d\n' "${progname}" \ "${success_file_cnt}" "${clean_file_cnt}" \ "$((success_file_cnt + clean_file_cnt))" "${total_file_cnt}"