#!/usr/bin/env bash usage() { cat < ] [ ] Run git grep and then send results to sed for replacement with the given flags, if they are provided via -f or as the third argument. Also runs git commit if -c is provided. EOF } # don't commit by default do_commit() { true } pathspec= while [ "$1" != "" ]; do case "$1" in -c|--commit) if git status --porcelain | grep .; then echo "you need to commit your changes before running with --commit" exit 1 fi do_commit() { git commit -m"replace $search with $replacement actual command: $command" -a } ;; -f|--flags) if [ "$2" = "" ]; then usage echo "missing argument for $1" exit 1 fi shift flags=$1 ;; -h|--help) usage exit ;; --) pathspec="$*" break ;; -*) usage echo "unknown flag: $1" exit 1 ;; *) if [ "$search" = "" ]; then search="$1" elif [ "$replacement" = "" ]; then replacement="$1" elif [ "$flags" = "" ]; then flags="$1" else usage echo "too many arguments: $1" exit 1 fi ;; esac shift done all="$search$replacement$flags" case "$all" in */*) ascii="$(for((i=32;i<=127;i++)) do printf '%b' "\\$(printf '%03o' "$i")"; done)" escaped="${all//-/\\-}" escaped="${escaped//[/\\[}" sep="$(printf '%s' "$ascii" | tr -d "$escaped")" sep="$(printf %.1s "$sep")" if [ "$sep" = "" ] ; then echo 'could not find an unused character for sed separator character' exit 1 fi ;; *) sep=/ ;; esac r=$(xargs -r false < /dev/null > /dev/null 2>&1 && echo r) need_bak=$(sed -i s/hello/world/ "$(git_extra_mktemp)" > /dev/null 2>&1 || echo true) if [ "$need_bak" ]; then command="git grep -lz '$search' $pathspec | xargs -0$r sed -i '' 's$sep$search$sep$replacement$sep$flags'" # shellcheck disable=SC2086 git grep -lz "$search" $pathspec | xargs -0"$r" sed -i '' "s$sep$search$sep$replacement$sep$flags" else command="git grep -lz '$search' $pathspec | xargs -0$r sed -i 's$sep$search$sep$replacement$sep$flags'" # shellcheck disable=SC2086 git grep -lz "$search" $pathspec | xargs -0"$r" sed -i "s$sep$search$sep$replacement$sep$flags" fi do_commit