My build of nnn with minor changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

154 line
3.3 KiB

  1. #!/usr/bin/env bash
  2. # Description: An almost fully POSIX compliant batch file renamer
  3. #
  4. # Note: nnn auto-detects and invokes this plugin if available
  5. # Whitespace is used as delimiter for read.
  6. # The plugin doesn't support filenames with leading or trailing whitespace
  7. #
  8. # Capabilities:
  9. # 1. Basic file rename
  10. # 2. Detects order change
  11. # 3. Can move files
  12. # 4. Can remove files
  13. # 5. Switch number pairs to swap filenames
  14. #
  15. # Shell: bash
  16. # Author: KlzXS
  17. EDITOR="${EDITOR:-vi}"
  18. TMPDIR="${TMPDIR:-/tmp}"
  19. INCLUDE_HIDDEN="${INCLUDE_HIDDEN:-0}"
  20. VERBOSE="${VERBOSE:-0}"
  21. selection=${NNN_SEL:-${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.selection}
  22. exit_status=0
  23. dst_file=$(mktemp "$TMPDIR/.nnnXXXXXX")
  24. if [ -s "$selection" ]; then
  25. printf "Rename 'c'urrent / 's'election? "
  26. read -r resp
  27. if ! [ "$resp" = "c" ] && ! [ "$resp" = "s" ]; then
  28. exit 1
  29. fi
  30. fi
  31. if [ "$resp" = "s" ]; then
  32. arr=$(tr '\0' '\n' < "$selection")
  33. else
  34. if [ "$INCLUDE_HIDDEN" -eq 0 ]; then
  35. arr=$(find . ! -name . -prune ! -name ".*" -print | sort)
  36. else
  37. arr=$(find . ! -name . -prune -print | sort)
  38. fi
  39. fi
  40. lines=$(printf "%s\n" "$arr" | wc -l)
  41. width=${#lines}
  42. printf "%s" "$arr" | awk '{printf("%'"${width}"'d %s\n", NR, $0)}' > "$dst_file"
  43. items=("~")
  44. while IFS='' read -r line; do
  45. items+=("$line");
  46. done < <(printf "%s\n" "$arr")
  47. $EDITOR "$dst_file"
  48. while read -r num name; do
  49. if [ -z "$name" ]; then
  50. if [ -z "$num" ]; then
  51. continue
  52. fi
  53. printf "%s: unable to parse line, aborting\n" "$0"
  54. exit 1
  55. fi
  56. # check if $num is an integer
  57. if [ ! "$num" -eq "$num" ] 2> /dev/null; then
  58. printf "%s: unable to parse line, aborting\n" "$0"
  59. exit 1
  60. fi
  61. src=${items[$num]}
  62. if [ -z "$src" ]; then
  63. printf "%s: unknown item number %s\n" "$0" "$num" > /dev/stderr
  64. continue
  65. elif [ "$name" != "$src" ]; then
  66. if [ -z "$name" ]; then
  67. continue
  68. fi
  69. if [ ! -e "$src" ] && [ ! -L "$src" ]; then
  70. printf "%s: %s does not exit\n" "$0" "$src" > /dev/stderr
  71. unset "items[$num]"
  72. continue
  73. fi
  74. # handle swaps
  75. if [ -e "$name" ] || [ -L "$name" ]; then
  76. tmp="$name~"
  77. c=0
  78. while [ -e "$tmp" ] || [ -L "$tmp" ]; do
  79. c=$((c+1))
  80. tmp="$tmp~$c"
  81. done
  82. if mv "$name" "$tmp"; then
  83. if [ "$VERBOSE" -ne 0 ]; then
  84. printf "'%s' -> '%s'\n" "$name" "$tmp"
  85. fi
  86. else
  87. printf "%s: failed to rename %s to %s: %s\n" "$0" "$name" "$tmp" "$!" > /dev/stderr
  88. exit_status=1
  89. fi
  90. for key in "${!items[@]}"; do
  91. if [ "${items[$key]}" = "$name" ]; then
  92. items[$key]="$tmp"
  93. fi
  94. done
  95. fi
  96. dir=$(dirname "$name")
  97. if [ ! -d "$dir" ] && ! mkdir -p "$dir"; then
  98. printf "%s: failed to create directory tree %s\n" "$0" "$dir" > /dev/stderr
  99. exit_status=1
  100. elif ! mv "$src" "$name"; then
  101. printf "%s: failed to rename %s to %s: %s\n" "$0" "$name" "$tmp" "$!" > /dev/stderr
  102. exit_status=1
  103. else
  104. if [ -d "$name" ]; then
  105. for key in "${!items[@]}"; do
  106. items[$key]=$(printf "%s" "${items[$key]}" | sed "s|^$src\(\$\|\/\)|$name\1|")
  107. done
  108. if [ "$VERBOSE" -ne 0 ]; then
  109. printf "'%s' => '%s'\n" "$src" "$name"
  110. fi
  111. else
  112. true
  113. if [ "$VERBOSE" -ne 0 ]; then
  114. printf "'%s' -> '%s'\n" "$src" "$name"
  115. fi
  116. fi
  117. fi
  118. fi
  119. unset "items[$num]"
  120. done <"$dst_file"
  121. unset "items[0]"
  122. for item in "${items[@]}"; do
  123. rm -ri "$item"
  124. done
  125. rm "$dst_file"
  126. exit $exit_status