# rename files to strip all special characters. # usage: name [FILES] name() { local targets=("${@}") # target file(s). local count=0 # processed count. local total=${#} # total to process. # all targets except hidden by default. if [[ "${targets}" = "" ]]; then targets=([^.]*) total=${#targets[@]} fi # process. for target in "${targets[@]}"; do # increment counter. ((count++)) # parse new name. local ext="" local name="${target}" # ext only for files. if [[ -f "${target}" ]]; then ext=".${target##*.}" name="${target%.*}" fi # Files w/o extension support. [[ "${ext#.}" = "${name}" ]] && ext="" # Get new name. local new_name=$(parse_simplify "${name}")${ext,,} # status line. local status="[${count}/${total}] ${target} -> ${new_name}" # check if same name. if [[ "${target}" = "${new_name}" ]]; then echo -e "${color_green}${status}: No change.${color_default}" continue fi # check if target name already exists. if [[ -f "${new_name}" ]]; then echo -e "${color_bred}${status}: already exists!${color_default}" return 1 fi # rename target. mv -- "${target}" "${new_name}" &> /dev/null # show change. echo -e "${color_default}${status}${color_default}" done } # rename all files to their hashes while keeping extensions. # usage: name_hash [FILES] name_hash() { local targets=("${@}") # target file(s). local count=0 # processed counter. local total=${#} # total to process. # all targets except hidden by default. if [[ "${targets}" = "" ]]; then targets=([^.]*) total=${#targets[@]} fi # process. for target in "${targets[@]}"; do # process only files. if [[ -f "${target}" ]]; then # increment count. ((count++)) # extract extension. local extension="${target##*.}" if [[ "${extension}" = "${target}" ]]; then extension="" else extension=".${extension}" fi # hash the new name. local hash=$(sha1sum -- "${target}" | cut -d\ -f1) new_name="${hash,,}${extension,,}" # prepare status. local status="[${count}/${total}] ${target} -> ${new_name}" # check if same name. if [[ "${target}" = "${new_name}" ]]; then echo -e "${color_green}${status}: No change.${color_default}" continue fi # rename target. mv -- "${target}" "${new_name}" &> /dev/null # show change. echo -e "${color_default}${status}${color_default}" else # Increment count. ((count++)) # Report skip. echo -e "${color_green}[${count}/${total}] ${target}: Skipping directory.${color_default}" fi done } # check hashes for renamed files. # usage: name_hash_check [FILES] name_hash_check() { local targets=("${@}") # target file(s). local total=${#} # total to process. local count=0 # processed counter. local failed=0 # failed to process counter. # all targets by default. if [[ "${targets}" = "" ]]; then targets=([^.]*) total=${#targets[@]} fi # process. for target in "${targets[@]}"; do # process only files. if [[ -f "${target}" ]]; then # increment count. ((count++)) # status info. local status="[${count}/${total}] ${target}" # extract hashes. local stored="${target%%.*}" local actual=$(sha1sum -- "${target}" | cut -d\ -f1) # compare hashes. if [[ "${stored}" = "${actual}" ]]; then echo -e "${color_default}${status}: Validation OK.${color_default}" else echo -e "${color_bred}${status}: Validation failed.${color_default}" ((failed++)) fi else # Increment count. ((count++)) # Report skip. echo -e "${color_green}[${count}/${total}] ${target}: Skipping directory.${color_default}" fi done # report result. if [[ ${count} -gt 1 ]]; then if [[ ${failed} -gt 0 ]]; then echo -e "${color_bred}Items failed to validate: ${failed}.${color_default}" else echo -e "${color_green}All successful.${color_default}" fi fi } # rename files for Jellyfin series, i.e. Episode S01E01.mkv # usage: name_series [FILES] name_series() { local season="${1}" # Season number. local targets=("${@:2}") # Target files. local count=0 # Processed counter. local episode=0 # Current episode count. local total=${#} # Total to process. # error when no season number specified. if [[ "${season}" = "" ]]; then echo "usage: name_series [FILES]" return 1 fi # all targets by default. if [[ "${targets}" = "" ]]; then targets=([^.]*) total=${#targets[@]} fi # process. for target in "${targets[@]}"; do # process only targets. if [[ -f "${target}" ]]; then # increment episode number. ((count++)) ((episode++)) # extract new name. local new_name="Episode S${season}E$(printf %02d ${episode}).${target##*.}" # prepare status. local status="[${count}/${total}] ${target} -> ${new_name}" # Warning on no change. if [[ "${target}" = "${new_name}" ]]; then echo -e "${color_green}${status}: No change.${color_default}" continue fi # rename target. mv -- "${target}" "${new_name}" &> /dev/null # Report status. echo -e "${color_default}${status}${color_default}" else # Increment count. ((count++)) # Report skip. echo -e "${color_green}[${count}/${total}] ${target}: Skipping directory.${color_default}" fi done } # rename files for Kavita manga format. # usage: name_manga [FILES] name_manga() { local season="${1}" # Season number. local targets=("${@:2}") # Target files. local count=0 # Processed counter. local episode=0 # Current episode count. local total=${#} # Total to process. local manga="${PWD##*/}" # Manga name. # error when no season number specified. if [[ "${season}" = "" ]]; then echo "usage: name_manga [FILES]" return 1 fi # all targets by default. if [[ "${targets}" = "" ]]; then targets=([^.]*) total=${#targets[@]} fi # process. for target in "${targets[@]}"; do # process only targets. if [[ -f "${target}" ]]; then # increment episode number. ((count++)) ((episode++)) # extract new name. local new_name="${manga} Vol.${season} Ch.${episode}.${target##*.}" # prepare status. local status="[${count}/${total}] ${target} -> ${new_name}" # Warning on no change. if [[ "${target}" = "${new_name}" ]]; then echo -e "${color_green}${status}: No change.${color_default}" continue fi # rename target. mv -- "${target}" "${new_name}" &> /dev/null # Show status. echo -e "${color_default}${status}${color_default}" else # Increment count. ((count++)) # Report skip. echo -e "${color_green}[${count}/${total}] ${target}: Skipping directory.${color_default}" fi done } # rename files for new extension. # usage: name_ext [FILES] name_ext() { local extension="${1}" # new extension. local targets=("${@:2}") # target file(s). local count=0 # processed counter. local total=$((${#}-1)) # total to process. # error when no new extension specified. if [[ "${extension}" = "" ]]; then echo "usage: name_ext [FILES]" return 1 fi # all targets by default. if [[ "${targets}" = "" ]]; then targets=([^.]*) total=${#targets[@]} fi # process. for target in "${targets[@]}"; do # process only targets. if [[ -f "${target}" ]]; then # increment count. ((count++)) # extract new name. local new_name="${target%.*}"."${extension}" # Prepare status. local status="[${count}/${total}] ${target} -> ${new_name}" # Warning on no change. if [[ "${target}" = "${new_name}" ]]; then echo -e "${color_green}${status}: No change.${color_default}" continue fi # rename target. mv -- "${target}" "${new_name}" &> /dev/null # show change. echo -e "${color_default}${status}${color_default}" else # Increment count. ((count++)) # Report skip. echo -e "${color_green}[${count}/${total}] ${target}: Skipping directory.${color_default}" fi done } # Change file's prefixes. # Usage: name_prefix [OLD] [NEW] [FILES] name_prefix() { local old="${1}" # Old prefix. local new="${2}" # New prefix. local targets=("${@:3}") # Target files. local count=0 # Total files processed. local total=$((${#}-2)) # Total files to process. # All targets by default. if [[ "${targets}" = "" ]]; then targets=([^.]*) total=${#targets[@]} fi # Process. for target in "${targets[@]}"; do # Increment counter. ((count++)) # Create new name. local new_name="${new}${target#$old}" # Prepare status. local status="[${count}/${total}] ${target} -> ${new_name}" # Warning on no change. if [[ "${target}" = "${new_name}" ]]; then echo -e "${color_green}${status}: No change.${color_default}" continue fi # Rename. mv -- "${target}" "${new_name}" &> /dev/null # Show change. echo -e "${color_default}${status}${color_default}" done } # export for parallel. export -f name name_hash name_hash_check name_ext