summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
authorbh <qn+git@epicurus.dev>2026-03-31 12:25:31 +0800
committerbh <qn+git@epicurus.dev>2026-03-31 12:25:31 +0800
commit02fdbdb604a142cb06213fcd5d43fbd3c830d409 (patch)
tree4ec1a192f327430de02b8d78b72db59f08ceb27a /scripts
parente275e093b09e76a3cee3ba15e2a162345f1298ca (diff)
Add vimv command
Diffstat (limited to 'scripts')
-rwxr-xr-xscripts/Scripts/vimv66
1 files changed, 66 insertions, 0 deletions
diff --git a/scripts/Scripts/vimv b/scripts/Scripts/vimv
new file mode 100755
index 0000000..83518ad
--- /dev/null
+++ b/scripts/Scripts/vimv
@@ -0,0 +1,66 @@
+#!/usr/bin/env bash
+set -eu
+
+# Lists the current directory's files in Vim, so you can edit it and save to rename them
+# USAGE: vimv [file1 file2]
+# https://github.com/thameera/vimv
+
+declare -r FILENAMES_FILE=$(mktemp "${TMPDIR:-/tmp}/vimv.XXXXXX")
+
+trap '{ rm -f "${FILENAMES_FILE}" ; }' EXIT
+
+safeMove() {
+ local src="$1"
+ local dest="$2"
+ mkdir -p "$(dirname "$dest")"
+ if [ -e "$dest" ]; then
+ echo "WARN: Can't rename '$src' -> '$dest', destination exists!" >&2
+ return 1
+ fi
+ if git ls-files --error-unmatch "$src" > /dev/null 2>&1; then
+ git mv -- "$src" "$dest"
+ else
+ mv -n -- "$src" "$dest"
+ fi
+}
+
+if [ $# -ne 0 ]; then
+ src=( "$@" )
+else
+ IFS=$'\r\n' GLOBIGNORE='*' command eval 'src=($(ls -1A))'
+fi
+
+for ((i=0;i<${#src[@]};++i)); do
+ echo "${src[i]}" >> "${FILENAMES_FILE}"
+done
+
+${EDITOR:-vi} "${FILENAMES_FILE}"
+
+IFS=$'\r\n' GLOBIGNORE='*' command eval 'dest=($(cat "${FILENAMES_FILE}"))'
+IFS=$'\r\n' GLOBIGNORE='*' command eval 'dest_unique=($(cat "${FILENAMES_FILE}" | sort -u))'
+
+if (( ${#src[@]} != ${#dest[@]} )); then
+ echo "WARN: Number of files changed. Did you delete a line by accident? Aborting.." >&2
+ exit 1
+fi
+
+if (( ${#dest[@]} != ${#dest_unique[@]} )); then
+ echo "WARN: Destination filenames are not unique! Aborting.." >&2
+ exit 1
+fi
+
+declare -i count=0
+EXT="vimv-tmp-$(date +%s)-${RANDOM}"
+for ((i=0;i<${#src[@]};++i)); do
+ if [ "${src[i]}" != "${dest[i]}" ]; then
+ safeMove "${src[i]}" "${dest[i]}.${EXT}" && ((++count))
+ fi
+done
+
+for ((i=0;i<${#src[@]};++i)); do
+ if [ "${src[i]}" != "${dest[i]}" ]; then
+ safeMove "${dest[i]}.${EXT}" "${dest[i]}" || : resume on error
+ fi
+done
+
+echo "$count" files renamed.