From f6ff9ae4aaf9bc60e07abfee70ff27b102e17558 Mon Sep 17 00:00:00 2001 From: KlzXS Date: Sun, 8 Mar 2020 02:45:11 +0100 Subject: [PATCH] POSIX compliant batchrename plugin (#488) * Added (almost) POSIX compliant batch rename script * Not fully * Added selection/current prompt --- plugins/batchrename | 184 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100755 plugins/batchrename diff --git a/plugins/batchrename b/plugins/batchrename new file mode 100755 index 00000000..23dc9a3f --- /dev/null +++ b/plugins/batchrename @@ -0,0 +1,184 @@ +#!/usr/bin/env sh + +# Description: An almost fully POSIX compliant batch file renamer +# +# Shell: POSIX compliant +# Author: KlzXS + +EDITOR="${EDITOR:-vi}" +TMPDIR="${TMPDIR:-/tmp}" +INCLUDE_HIDDEN="${INCLUDE_HIDDEN:-0}" + +selection=${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.selection +exit_status=0 + +dst_file=$(mktemp "$TMPDIR/.nnnXXXXXX") + +if [ -s "$selection" ]; then + printf "Rename 'c'urrent / 's'election? " + read -r resp +fi + +if [ "$resp" = "s" ]; then + arr=$(tr '\0' '\n' < "$selection") +else + if [ "$INCLUDE_HIDDEN" -eq 0 ]; then + arr=$(find . ! -name . -prune ! -name ".*" -print | sort) + else + arr=$(find . ! -name . -prune -print | sort) + fi +fi + +printf "%s" "$arr" | awk '{print NR " " $0}' > "$dst_file" +arr=$(printf "%s" "$arr" | sed "s/'/'\\\\''/g;s/^\(.*\)$/'\1'/" | tr '\n' ' ') + +eval "set -- $arr" +$EDITOR "$dst_file" + +while read -r num name; do + if [ -z "$name" ]; then + if [ -z "$num" ]; then + continue + fi + + printf "%s: unable to parse line, aborting\n" "$0" + fi + + # check if $num is an integer + if [ ! "$num" -eq "$num" ] 2> /dev/null; then + printf "%s: unable to parse line, aborting\n" "$0" + fi + + src=$(eval printf "%s" "\${$num}") + + if [ -z "$src" ]; then + printf "%s: unknown item number %s\n" "$0" "$num" > /dev/stderr + continue + elif [ "$name" != "$src" ]; then + if [ -z "$name" ]; then + continue + fi + + if [ ! -e "$src" ] && [ ! -L "$src" ]; then + printf "%s: %s does not exit\n" "$0" "$src" > /dev/stderr + + c=1 + new_args="" + while [ $c -le $# ]; do + tmp=$(eval printf "%s" "\${$c}") + if [ "$c" -eq "$num" ]; then + new_args="$new_args ''" + else + if [ -z "$tmp" ]; then + tmp="''" + else + tmp=$(printf %s "$tmp" | sed "s/'/'\\\\''/g;s/^\(.*\)$/'\1'/") + fi + new_args="$new_args $tmp" + fi + c=$((c+1)) + done + + eval "set -- $new_args" + continue + fi + + # handle swaps + if [ -e "$name" ] || [ -L "$name" ]; then + tmp="$name~" + c=0 + + while [ -e "$tmp" ] || [ -L "$tmp" ]; do + c=$((c+1)) + tmp="$tmp~$c" + done + + if mv "$name" "$tmp"; then + printf "'%s' -> '%s'\n" "$name" "$tmp" + else + printf "%s: failed to rename %s to %s: %s\n" "$0" "$name" "$tmp" "$!" > /dev/stderr + exit_status=1 + fi + + c=1 + new_args="" + while [ $c -le $# ]; do + item=$(eval printf "%s" "\${$c}") + if [ "$item" = "$name" ]; then + item=$(printf %s "$tmp" | sed "s/'/'\\\\''/g;s/^\(.*\)$/'\1'/") + new_args="$new_args $item" + else + if [ -z "$item" ]; then + item="''" + else + item=$(printf %s "$item" | sed "s/'/'\\\\''/g;s/^\(.*\)$/'\1'/") + fi + new_args="$new_args $item" + fi + c=$((c+1)) + done + + eval "set -- $new_args" + fi + + dir=$(dirname "$name") + if [ ! -d "$dir" ] && ! mkdir -p "$dir"; then + printf "%s: failed to create directory tree %s\n" "$0" "$dir" > /dev/stderr + exit_status=1 + elif ! mv "$src" "$name"; then + printf "%s: failed to rename %s to %s: %s\n" "$0" "$name" "$tmp" "$!" > /dev/stderr + exit_status=1 + else + printf "'%s' -> '%s'\n" "$src" "$name" + if [ -d "$name" ]; then + c=1 + new_args="" + while [ $c -le $# ]; do + tmp=$(eval printf "\${$c}") + if [ -z "$tmp" ]; then + tmp="''" + else + tmp=$(printf "%s" "$tmp" | sed "s/^$src\(\$\|\/\)/$name\1/;s/'/'\\\\''/g;s/^\(.*\)$/'\1'/") + fi + new_args="$new_args $tmp" + c=$((c+1)) + done + + eval "set -- $new_args" + printf "'%s' => '%s'\n" "$src" "$name" + fi + fi + fi + + c=1 + new_args="" + while [ $c -le $# ]; do + tmp=$(eval printf "%s" "\${$c}") + if [ "$c" -eq "$num" ]; then + new_args="$new_args ''" + else + if [ -z "$tmp" ]; then + tmp="''" + else + tmp=$(printf %s "$tmp" | sed "s/'/'\\\\''/g;s/^\(.*\)$/'\1'/") + fi + new_args="$new_args $tmp" + fi + c=$((c+1)) + done + + eval "set -- $new_args" +done <"$dst_file" + +c=1 +new_args="" +while [ $c -le $# ]; do + tmp=$(eval printf "%s" "\${$c}") + if [ -n "$tmp" ]; then + rm -ri "$tmp" + fi + c=$((c+1)) +done + +rm "$dst_file" +exit $exit_status