# Rename files to strip all special characters. # All files by default. # Usage: name [FILES] function name() { local IFS=$'\n' local targets=("${@}") local count=0 local total=${#} local failed=0 # 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}" echo -e "${color_bwhite}${status}${color_default}" # check if same name. [[ "${target}" = "${new_name}" ]] && continue # check if target name already exists. if [[ -f "${new_name}" ]]; then echo -e "${color_bred}${status}: already exists!${color_default}" ((failed++)) fi # rename target. mv -- "${target}" "${new_name}" if [[ ${?} != 0 ]]; then echo -e "${color_bred}${status}: Failed.${color_default}" ((failed++)) fi done if [[ ${failed} != 0 ]]; then echo -e "${color_bred}Failed: ${failed}.${color_default}" false fi } # Rename all files to their hashes while keeping extensions. # All files by default. # Usage: name_hash [FILES] function name_hash() { local IFS=$'\n' local targets=("${@}") local count=0 local total=${#} local failed=0 # all files except hidden by default. if [[ "${targets}" = "" ]]; then targets=($(ls --classify | grep -v /\$)) total=${#targets[@]} fi # process. for target in "${targets[@]}"; do # increment count. ((count++)) # extract extension. local extension="${target##*.}" if [[ "${extension}" = "${target}" ]]; then extension="" else extension=".${extension}" fi # hash the new name. local hash=$(pv "${target}" | sha1sum | 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}" echo -e "${color_bwhite}${status}${color_default}" continue fi # show change. echo -e "${color_bwhite}${status}${color_default}" # rename target. mv -- "${target}" "${new_name}" if [[ ${?} != 0 ]]; then echo -e "${color_bred}${status}: Failed.${color_default}" ((failed++)) fi done if [[ ${failed} != 0 ]]; then echo -e "${color_bred}Failed: ${failed}.${color_default}" false fi } # Check hashes for previously renamed files. # All files by default. # Usage: name_hash_check [FILES] function name_hash_check() { local IFS=$'\n' local targets=("${@}") local total=${#} local count=0 local failed=0 # all targets by default. if [[ "${targets}" = "" ]]; then targets=($(ls --classify | grep -v /\$)) total=${#targets[@]} fi # process. for target in "${targets[@]}"; do # increment count. ((count++)) # status info. local status="[${count}/${total}] ${target}" echo -e "${color_bwhite}${status}${color_default}" # extract hashes. local stored="${target%%.*}" local actual=$(pv "${target}" | sha1sum | cut -d\ -f1) # compare hashes. if [[ "${stored}" != "${actual}" ]]; then echo -e "${color_bred}${status}: Failed.${color_default}" ((failed++)) fi done if [[ ${failed} != 0 ]]; then echo -e "${color_bred}Failed: ${failed}.${color_default}" false fi } # Rename files for Jellyfin series, i.e. `Episode S01E01.mkv` # All files by default. # Usage: name_series [FILES] function name_series() { local IFS=$'\n' local season="${1}" local targets=("${@:2}") local count=0 local episode=0 local total=${#} local failed=0 # error when no season number specified. if [[ "${season}" = "" ]]; then echo "usage: name_series [FILES]" return 2 fi # all targets by default. if [[ "${targets}" = "" ]]; then targets=($(ls --classify | grep -v /\$)) total=${#targets[@]} fi # process. for target in "${targets[@]}"; do # 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}" echo -e "${color_bwhite}${status}${color_default}" # Warning on no change. [[ "${target}" = "${new_name}" ]] && continue # rename target. mv -- "${target}" "${new_name}" if [[ ${?} != 0 ]]; then echo -e "${color_bred}${status}: Failed.${color_default}" ((failed++)) fi done if [[ ${failed} != 0 ]]; then echo -e "${color_bred}Failed: ${failed}.${color_default}" false fi } # Rename files for Kavita manga format. # All files by default. # Usage: name_manga [FILES] function name_manga() { local IFS=$'\n' local season="${1}" local targets=("${@:2}") local count=0 local episode=0 local total=${#} local manga="${PWD##*/}" local failed=0 # error when no season number specified. if [[ "${season}" = "" ]]; then echo "usage: name_manga [FILES]" return 2 fi # all targets by default. if [[ "${targets}" = "" ]]; then targets=($(ls --classify | grep -v /\$)) total=${#targets[@]} fi # process. for target in "${targets[@]}"; do # 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}" echo -e "${status}" # Warning on no change. [[ "${target}" = "${new_name}" ]] && continue # rename target. mv -- "${target}" "${new_name}" if [[ ${?} != 0 ]]; then echo -e "${color_bred}${status}: Failed.${color_default}" ((failed++)) fi done if [[ ${failed} != 0 ]]; then echo -e "${color_bred}Failed: ${failed}.${color_default}" false fi } # Rename files with new extension. # All files by default. # Usage: name_ext [FILES] function name_ext() { local IFS=$'\n' local extension="${1}" local targets=("${@:2}") local count=0 local total=$((${#}-1)) local failed=0 # error when no new extension specified. if [[ "${extension}" = "" ]]; then help name_ext return 2 fi # all targets by default. if [[ "${targets}" = "" ]]; then targets=($(ls --classify | grep -v /\$)) total=${#targets[@]} fi # process. for target in "${targets[@]}"; do # increment count. ((count++)) # extract new name. local new_name="${target%.*}"."${extension}" # Prepare status. local status="[${count}/${total}] ${target} -> ${new_name}" echo -e "${color_bwhite}${status}${color_default}" # Warning on no change. [[ "${target}" = "${new_name}" ]] && continue # rename target. mv -- "${target}" "${new_name}" if [[ ${?} != 0 ]]; then echo -e "${color_bred}${status}: Failed.${color_default}" ((failed++)) fi done if [[ ${failed} != 0 ]]; then echo -e "${color_bred}Failed: ${failed}.${color_default}" false fi } # Change file name prefix. # All matching files by default. # Usage: name_prefix [FILES] function name_prefix() { local IFS=$'\n' local old="${1}" local new="${2}" local targets=("${@:3}") local count=0 local total=$((${#}-2)) local failed=0 # All matching targets by default. if [[ "${targets}" = "" ]]; then targets=(${old}*) 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}" echo -e "${color_bwhite}${status}${color_default}" # Warning on no change. [[ "${target}" = "${new_name}" ]] && continue # Rename. mv -- "${target}" "${new_name}" if [[ ${?} != 0 ]]; then echo -e "${color_bred}${status}: Failed.${color_default}" ((failed++)) fi done if [[ ${failed} != 0 ]]; then echo -e "${color_bred}Failed: ${failed}.${color_default}" false fi } # Change file name postfix. # All matching files by default. # Usage: name_postfix [FILES] function name_postfix() { local IFS=$'\n' local old="${1}" local new="${2}" local targets=("${@:3}") local count=0 local total=$((${#}-2)) local failed=0 # All matching targets by default. if [[ "${targets}" = "" ]]; then targets=(*${old}) total=${#targets[@]} fi # Process. for target in "${targets[@]}"; do # Increment counter. ((count++)) # Create new name. local new_name="${target%$old}${new}" # Prepare status. local status="[${count}/${total}] ${target} -> ${new_name}" echo -e "${color_bwhite}${status}${color_default}" # Warning on no change. [[ "${target}" = "${new_name}" ]] && continue # Rename. mv -- "${target}" "${new_name}" if [[ ${?} != 0 ]]; then echo -e "${color_bred}${status}: Failed.${color_default}" ((failed++)) fi done if [[ ${failed} != 0 ]]; then echo -e "${color_bred}Failed: ${failed}.${color_default}" false fi } # Replace part of the name. # All matching files by default. # Usage: name_replace [FILES] function name_replace() { local IFS=$'\n' local old="${1}" local new="${2}" local targets=("${@:3}") local count=0 local total=$((${#}-2)) local failed=0 # All matching targets by default. if [[ "${targets}" = "" ]]; then targets=(*${old}*) total=${#targets[@]} fi # Process. for target in "${targets[@]}"; do # Increment counter. ((count++)) # Create new name. local new_name="${target//$old/$new}" # Prepare status. local status="[${count}/${total}] ${target} -> ${new_name}" echo -e "${color_bwhite}${status}${color_default}" # Warning on no change. [[ "${target}" = "${new_name}" ]] && continue # Rename. mv -- "${target}" "${new_name}" if [[ ${?} != 0 ]]; then echo -e "${color_bred}${status}: Failed.${color_default}" ((failed++)) fi done if [[ ${failed} != 0 ]]; then echo -e "${color_bred}Failed: ${failed}.${color_default}" false fi } # Fix numbering for numbered files. I.e if there are 10 items and some of them start without zero, then append zero to it. 1..10 -> 01..10. # Usage: name_fix_numbering [FILES] function name_fix_numbering() { local IFS=$'\n' local targets=("${@}") local count=0 local total=${#} local failed=0 local power=0 # All files by default. if [[ "${targets[*]}" = "" ]]; then targets=($(ls | grep "^[0-9]")) total=${#targets[@]} fi # Count leading zeroes. local highest=0 for target in "${targets[@]}"; do # Check that starts with a digit. [[ "${target}" =~ ^[0-9] ]] || continue local digits=($(_parse_ints "${target}")) local digit="${digits[0]}" digit=$((10#${digit})) [[ "${digit}" -gt "${highest}" ]] && highest="${digit}" done local i=${highest} while [[ i -gt 0 ]]; do ((power++)) i=$((${i}/10)) done # Process. for target in "${targets[@]}"; do ((count++)) local status="[${count}/${total}] ${target}" # Check that starts with a digit. if [[ ! "${target}" =~ ^[0-9] ]]; then echo -e "${color_bwhite}${status}${color_default}" continue fi # Prepare new name. local digits=($(_parse_ints "${target}")) local digit="${digits[0]}" digit=$((10#${digit})) local new_name=$(printf "%0${power}d" "${digit}")"${target#${digits[0]}}" status="${status} -> ${new_name}" # Skip if the same. if [[ "${target}" = "${new_name}" ]]; then echo -e "${color_bwhite}${status}${color_default}" continue fi # Check that file does not exist. if [[ -e "${new_name}" ]]; then echo -e "${color_bred}${status}: File exists!${color_default}" return 1 fi echo -e "${color_bwhite}${status}${color_default}" mv -- "${target}" "${new_name}" if [[ ${?} != 0 ]]; then echo -e "${color_bred}${status}: Failed.${color_default}" ((failed++)) fi done if [[ ${failed} != 0 ]]; then echo -e "${color_bred}Failed: ${failed}.${color_default}" false fi }