1010# Options:
1111# -x, --exclude DIR Exclude a subdirectory (repeatable). Examples: -x node_modules -x build
1212# --include-hidden Include hidden directories (like .git, .venv).
13+ # -y, --yes Skip confirmation prompt (assume “yes” to proceed).
1314# -h, --help Show this help and exit.
1415#
1516# Examples:
1617# replace_everywhere.sh "cat" "dog"
1718# replace_everywhere.sh -x dist -x build 'string with space' 'new string'
1819# replace_everywhere.sh --include-hidden 'foo**' 'bar\baz'
20+ # replace_everywhere.sh -y 'old' 'new'
1921#
2022# Notes:
2123# - For literal matching, special chars are handled safely. Replacement also escapes '&' properly.
2426set -euo pipefail
2527
2628print_usage () {
27- sed -n ' 2,40p ' " $0 "
29+ sed -n ' 2,45p ' " $0 "
2830}
2931
3032# Escape a string for use as a *literal* sed pattern (s/…/…/)
3133escape_sed_pattern () {
32- # Escapes: \ / [ ] . ^ $ * and other regex metas so the pattern is treated literally
3334 printf ' %s' " $1 " | sed -e ' s/[.[\*^$\/]/\\&/g' -e ' s/]/\\]/g'
3435}
3536
@@ -43,6 +44,7 @@ escape_sed_replacement() {
4344
4445main () {
4546 local include_hidden=false
47+ local auto_yes=false
4648 local -a excludes=()
4749
4850 # Parse args (support short and long)
@@ -53,6 +55,8 @@ main() {
5355 excludes+=(" $2 " ); shift 2;;
5456 --include-hidden)
5557 include_hidden=true; shift ;;
58+ -y|--yes)
59+ auto_yes=true; shift ;;
5660 -h|--help)
5761 print_usage; exit 0;;
5862 --) shift ; break ;;
@@ -75,33 +79,31 @@ main() {
7579 search=$( escape_sed_pattern " $search_raw " )
7680 replace=$( escape_sed_replacement " $replace_raw " )
7781
78- # Confirm action
79- read -r -p " Replace ALL occurrences of '$search_raw ' with '$replace_raw ' in this tree? [y/N] " confirmation
80- if [[ ! $confirmation =~ ^[Yy]$ ]]; then
81- echo " Operation cancelled."
82- exit 1
82+ # Confirm action unless -y/--yes
83+ if [[ " $auto_yes " == false ]]; then
84+ read -r -p " Replace ALL occurrences of '$search_raw ' with '$replace_raw ' in this tree? [y/N] " confirmation
85+ if [[ ! $confirmation =~ ^[Yy]$ ]]; then
86+ echo " Operation cancelled."
87+ exit 1
88+ fi
8389 fi
8490
8591 # Detect GNU vs BSD sed for in-place flag
8692 local -a SED_INPLACE
8793 if sed --version > /dev/null 2>&1 ; then
8894 SED_INPLACE=(-i)
8995 else
90- # macOS/BSD sed needs a backup suffix (empty is allowed)
9196 SED_INPLACE=(-i ' ' )
9297 fi
9398
9499 # Build the find prune predicates
95- # Start with hidden directories (if not including them)
96100 local -a PRUNE_BLOCK=()
97101 if [[ " $include_hidden " == false ]]; then
98102 PRUNE_BLOCK+=( -path ' ./.*' -prune -o )
99103 fi
100104
101- # Add user-specified excludes (treat as directory names/paths from repo root)
102105 if [[ ${# excludes[@]} -gt 0 ]]; then
103106 for d in " ${excludes[@]} " ; do
104- # Normalize leading './'
105107 [[ " $d " != ./* ]] && d=" ./$d "
106108 PRUNE_BLOCK+=( -path " $d " -prune -o )
107109 done
0 commit comments