Last active
May 3, 2026 08:47
-
-
Save armamini/9347ebef13722694228402c2120c1208 to your computer and use it in GitHub Desktop.
Smart Recursive Search Tool (xrep)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # xrep by @armamini — colorful smart recursive search tool | |
| # ---------- Colors ---------- | |
| RED='\033[0;31m' | |
| GREEN='\033[0;32m' | |
| YELLOW='\033[1;33m' | |
| BLUE='\033[0;34m' | |
| CYAN='\033[0;36m' | |
| BOLD='\033[1m' | |
| NC='\033[0m' | |
| # ---------- Help ---------- | |
| show_help() { | |
| echo -e "${BOLD}${CYAN}" | |
| echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" | |
| echo " xrep" | |
| echo " Smart Recursive Search Utility" | |
| echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" | |
| echo -e "${NC}" | |
| echo -e "${YELLOW}Usage:${NC}" | |
| echo " xrep <file> \"text\"" | |
| echo " xrep -r \"text\"" | |
| echo " xrep -r -i \"text\"" | |
| echo " xrep -r -d \"folder_name\"" | |
| echo | |
| echo -e "${YELLOW}Options:${NC}" | |
| echo " -r Recursive search" | |
| echo " -i Case-insensitive" | |
| echo " -d Search directory names too" | |
| echo " -h Show help" | |
| echo | |
| echo -e "${YELLOW}Examples:${NC}" | |
| echo " xrep app.js \"Find me\"" | |
| echo " xrep -r \"TODO\"" | |
| echo " xrep -r -i \"password\"" | |
| echo " xrep -r -d \"controllers\"" | |
| echo | |
| exit 1 | |
| } | |
| # ---------- Flags ---------- | |
| RECURSIVE=false | |
| IGNORE_CASE=false | |
| SEARCH_DIRS=false | |
| while getopts ":ridh" opt; do | |
| case $opt in | |
| r) RECURSIVE=true ;; | |
| i) IGNORE_CASE=true ;; | |
| d) SEARCH_DIRS=true ;; | |
| h) show_help ;; | |
| \?) | |
| echo -e "${RED}✖ Invalid option: -$OPTARG${NC}" | |
| show_help | |
| ;; | |
| esac | |
| done | |
| shift $((OPTIND - 1)) | |
| # ---------- Grep Options ---------- | |
| GREP_ARGS=(-nH) | |
| if [ "$IGNORE_CASE" = true ]; then | |
| GREP_ARGS+=(-i) | |
| fi | |
| # ---------- Excluded Paths ---------- | |
| EXCLUDE_PATTERNS=( | |
| "*/node_modules/*" | |
| "*/.venv/*" | |
| "*/venv/*" | |
| "*/env/*" | |
| "*/__pycache__/*" | |
| "*/dist/*" | |
| "*/build/*" | |
| "*/coverage/*" | |
| "*/vendor/*" | |
| "*/target/*" | |
| "*/.next/*" | |
| "*/.nuxt/*" | |
| "*/.cache/*" | |
| "*/.pytest_cache/*" | |
| "*/.git/*" | |
| ) | |
| # ---------- Recursive Mode ---------- | |
| if [ "$RECURSIVE" = true ]; then | |
| if [ $# -ne 1 ]; then | |
| echo -e "${RED}✖ Recursive mode requires only a search string${NC}" | |
| show_help | |
| fi | |
| SEARCH_TERM="$1" | |
| echo -e "${BLUE}➜ Searching recursively for:${NC} ${BOLD}\"$SEARCH_TERM\"${NC}" | |
| echo | |
| if [ "$SEARCH_DIRS" = true ]; then | |
| echo -e "${CYAN}📁 Matching directories:${NC}" | |
| FIND_DIR_CMD=(find . -type d) | |
| for pattern in "${EXCLUDE_PATTERNS[@]}"; do | |
| FIND_DIR_CMD+=(! -path "$pattern") | |
| done | |
| if [ "$IGNORE_CASE" = true ]; then | |
| "${FIND_DIR_CMD[@]}" | grep -i -- "$SEARCH_TERM" | |
| else | |
| "${FIND_DIR_CMD[@]}" | grep -- "$SEARCH_TERM" | |
| fi | |
| echo | |
| fi | |
| echo -e "${CYAN}📄 Matching file contents:${NC}" | |
| FIND_FILE_CMD=(find . -type f) | |
| for pattern in "${EXCLUDE_PATTERNS[@]}"; do | |
| FIND_FILE_CMD+=(! -path "$pattern") | |
| done | |
| "${FIND_FILE_CMD[@]}" -print0 | xargs -0 grep "${GREP_ARGS[@]}" -- "$SEARCH_TERM" | |
| # ---------- Single File Mode ---------- | |
| else | |
| if [ $# -ne 2 ]; then | |
| echo -e "${RED}✖ File mode requires: file + search string${NC}" | |
| show_help | |
| fi | |
| TARGET_FILE="$1" | |
| SEARCH_TERM="$2" | |
| if [ ! -f "$TARGET_FILE" ]; then | |
| echo -e "${RED}✖ File not found:${NC} $TARGET_FILE" | |
| exit 1 | |
| fi | |
| echo -e "${BLUE}➜ Searching in file:${NC} ${BOLD}$TARGET_FILE${NC}" | |
| echo -e "${BLUE}➜ Search term:${NC} ${BOLD}\"$SEARCH_TERM\"${NC}" | |
| echo | |
| grep "${GREP_ARGS[@]}" -- "$SEARCH_TERM" "$TARGET_FILE" | |
| fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment