.nmv (3828B)
1 #!/usr/bin/env bash 2 3 # Description: An almost fully POSIX compliant batch file renamer 4 # 5 # Note: nnn auto-detects and invokes this plugin if available 6 # Whitespace is used as delimiter for read. 7 # The plugin doesn't support filenames with leading or trailing whitespace 8 # To use NNN_LIST your shell must support readlink(1) 9 # 10 # Capabilities: 11 # 1. Basic file rename 12 # 2. Detects order change 13 # 3. Can move files 14 # 4. Can remove files 15 # 5. Switch number pairs to swap filenames 16 # 17 # Shell: bash 18 # Author: KlzXS 19 20 # shellcheck disable=SC1090,SC1091 21 . "$(dirname "$0")"/.nnn-plugin-helper 22 23 EDITOR="${EDITOR:-vi}" 24 TMPDIR="${TMPDIR:-/tmp}" 25 NNN_INCLUDE_HIDDEN="${NNN_INCLUDE_HIDDEN:-0}" 26 VERBOSE="${VERBOSE:-0}" 27 RECURSIVE="${RECURSIVE:-0}" 28 29 case "$NNN_TRASH" in 30 1) 31 RM_UTIL="trash-put" ;; 32 2) 33 RM_UTIL="gio trash" ;; 34 "") 35 RM_UTIL="rm -ri --" ;; 36 *) 37 RM_UTIL="$NNN_TRASH" ;; 38 esac 39 40 exit_status=0 41 42 if nnn_use_selection "Rename"; then 43 # shellcheck disable=SC2154 44 arr=$(tr '\0' '\n' < "$selection") 45 else 46 findcmd="find . ! -name ." 47 48 if [ "$RECURSIVE" -eq 0 ]; then 49 findcmd="$findcmd -prune" 50 fi 51 52 if [ "$NNN_INCLUDE_HIDDEN" -eq 0 ]; then 53 findcmd="$findcmd ! -name \".*\"" 54 fi 55 56 if [ -z "$NNN_LIST" ]; then 57 findcmd="$findcmd -print" 58 else 59 findcmd="$findcmd -printf "'"'"$NNN_LIST/%P\n"'"' 60 fi 61 62 arr=$(eval "$findcmd" | sort) 63 fi 64 65 lines=$(printf "%s\n" "$arr" | wc -l) 66 width=${#lines} 67 68 dst_file=$(mktemp "$TMPDIR/.nnnXXXXXX") 69 trap 'rm -f -- "$dst_file"' EXIT 70 71 printf "%s" "$arr" | awk '{printf("%'"${width}"'d %s\n", NR, $0)}' > "$dst_file" 72 73 items=("~") 74 while IFS='' read -r line; do 75 if [ -n "$NNN_LIST" ]; then 76 line=$(readlink "$line" || printf "%s" "$line") 77 fi 78 79 items+=("$line"); 80 done < <(printf "%s\n" "$arr") 81 82 $EDITOR "$dst_file" 83 84 while read -r num name; do 85 if [ -z "$name" ]; then 86 if [ -z "$num" ]; then 87 continue 88 fi 89 90 printf "%s: unable to parse line, aborting\n" "$0" 91 exit 1 92 fi 93 94 # check if $num is an integer 95 if [ ! "$num" -eq "$num" ] 2> /dev/null; then 96 printf "%s: unable to parse line, aborting\n" "$0" 97 exit 1 98 fi 99 100 src=${items[$num]} 101 102 if [ -z "$src" ]; then 103 printf "%s: unknown item number %s\n" "$0" "$num" > /dev/stderr 104 continue 105 elif [ "$name" != "$src" ]; then 106 if [ -z "$name" ]; then 107 continue 108 fi 109 110 if [ ! -e "$src" ] && [ ! -L "$src" ]; then 111 printf "%s: %s does not exit\n" "$0" "$src" > /dev/stderr 112 113 unset "items[$num]" 114 continue 115 fi 116 117 # handle swaps 118 if [ -e "$name" ] || [ -L "$name" ]; then 119 tmp="$name~" 120 c=0 121 122 while [ -e "$tmp" ] || [ -L "$tmp" ]; do 123 c=$((c+1)) 124 tmp="$tmp~$c" 125 done 126 127 if mv -- "$name" "$tmp"; then 128 if [ "$VERBOSE" -ne 0 ]; then 129 printf "'%s' -> '%s'\n" "$name" "$tmp" 130 fi 131 else 132 printf "%s: failed to rename %s to %s: %s\n" "$0" "$name" "$tmp" "$!" > /dev/stderr 133 exit_status=1 134 fi 135 136 for key in "${!items[@]}"; do 137 if [ "${items[$key]}" = "$name" ]; then 138 # shellcheck disable=2004 139 items[$key]="$tmp" 140 fi 141 done 142 fi 143 144 dir=$(dirname "$name") 145 if [ ! -d "$dir" ] && ! mkdir -p "$dir"; then 146 printf "%s: failed to create directory tree %s\n" "$0" "$dir" > /dev/stderr 147 exit_status=1 148 elif ! mv -i -- "$src" "$name"; then 149 printf "%s: failed to rename %s to %s: %s\n" "$0" "$name" "$tmp" "$!" > /dev/stderr 150 exit_status=1 151 else 152 if [ -d "$name" ]; then 153 for key in "${!items[@]}"; do 154 # shellcheck disable=2004 155 items[$key]=$(printf "%s" "${items[$key]}" | sed "s|^$src\(\$\|\/\)|$name\1|") 156 done 157 158 if [ "$VERBOSE" -ne 0 ]; then 159 printf "'%s' => '%s'\n" "$src" "$name" 160 fi 161 else 162 true 163 if [ "$VERBOSE" -ne 0 ]; then 164 printf "'%s' -> '%s'\n" "$src" "$name" 165 fi 166 fi 167 fi 168 fi 169 170 unset "items[$num]" 171 done <"$dst_file" 172 173 unset "items[0]" 174 for item in "${items[@]}"; do 175 $RM_UTIL "$item" 176 done 177 178 exit $exit_status