Skip to content

Instantly share code, notes, and snippets.

@skull-squadron
Created May 30, 2024 02:36
Show Gist options
  • Save skull-squadron/5bd2c7f1f7717e09b5f26f2157ffae3d to your computer and use it in GitHub Desktop.
Save skull-squadron/5bd2c7f1f7717e09b5f26f2157ffae3d to your computer and use it in GitHub Desktop.
mass-rename files and change contents with sed
#!/usr/bin/env bash
[[ "${BASH_VERSINFO[0]}" -ge 4 ]] || {
echo >&2 'Requires bash >= 4'
exit 1
}
set -Eeuo pipefail
[ -z "${DEBUG-}" ] || set -x
if [ "$#" = 0 ]; then
cat >&2 << 'USAGE'
Usage: mass-rename {sed expression(s)} [directory]
The directory itself is *not* renamed.
NO WARRANTIES! Have tested backups before proceeding.
USAGE
exit 1
fi
if [ "${2-}" ]; then
cd "$2"
fi
case "$OSTYPE" in
darwin*|freebsd*|netbsd*|openbsd*)
inplace_replace() {
LC_ALL=C sed -i '' "$@"
}
;;
*)
inplace_replace() {
sed -i "$@"
}
esac
if git rev-parse --is-inside-work-tree &>/dev/null; then
if [ "$(git status --porcelain)" ]; then
echo >&2 'Git working directory unclean, aborting mass-rename'
exit 1
fi
trap 'e=$?; trap - EXIT; rm -rf "$T"; exit $e' EXIT
T="$(mktemp -d)"
all="$T/all"
ignores="$T/ignores"
find -E . -mindepth 1 ! -iregex '.*/\.git(/.*)?' | sort >"$all"
git check-ignore --stdin <"$all" >"$ignores" || true
readarray -t src_files < <(comm -23 "$all" "$ignores")
else
readarray -t src_files < <(find -E . -mindepth 1 | sort)
fi
delete_list=()
for src in "${src_files[@]}"; do
src=${src#\./}
if [ ! -d "$src" ] && file -b "$src" | grep -q text; then
inplace_replace "$1" "$src"
fi
dest=$(sed "$1" <<<"$src")
abs_dest="$PWD/$dest"
[ "$src" != "$dest" ] || continue
if [ -d "$src" ] ; then
if [ "$(readlink -f "$src")" != "$(readlink -f "$abs_dest")" ]; then
delete_list=("$src" "${delete_list[@]}")
mv -v "$src" "$dest"
ln -s "$abs_dest" "$src"
fi
else
mv -v "$src" "$dest"
fi
done
if [ "${#delete_list[@]}" != 0 ]; then
rm -f "${delete_list[@]}"
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment