How many times have grep’d a file, and then piped the output in order to grep again, and then piped that again to grep? Sometimes when I am search a file, I could end up piping maybe a dozen times while searching the file. Just for fun, I wanted to write a recursive grep program, rgrep in rust. However, as a first step, I figured I could write it in bash first.

In order to use associated arrays, you must first be using Bash 4, as earlier versions did not have this feature. I wrote this as simply as possible, so there very well could be bugs. I only wanted to write as lean a script as possible for preliminary testing.

rgrep.sh
#!/usr/bin/env bash

# Initialize array for search results
declare -A rloop

# Get array of args
args=($@)

# Get length of args array
arg_len=${#args[@]}

# Exit if too few args are passed
if [[ $arg_len -le 1 ]]
then
    echo "Please enter your args, followed by a trailing file to parse"
    exit 1
fi

# Get last arg
file=${args[$len-1]}

# Exit if $file does not exist
if [[ ! -e $file ]]
then
    echo "Could not access $file"
    exit 1
fi

# Get list of args ignoring the last arg
search_terms=${args[@]:0:${arg_len}-1}

# Loop over args
count=0
for i in ${search_terms[@]}
do
    if [[ $count == 0 ]]
    then
        # If we are on the first loop, then grep the file directly
        rloop[$count]=$(grep -i $i $file)
    else
        # Otherwise, grep the previous loop's content
        previous_loop=$((count-1))
        rloop[$count]=$(echo "${rloop[$previous_loop]}" | grep -i $i)
    fi
    count=$((count+1))
done

# Display search results
last_loop=$((count-1))
echo "${rloop[$last_loop]}"

Using rgrep.sh, we can search for lines that include the work “and”:

[admin@openbox coding_projects/shell]# ./rgrep.sh and poem.txt
Thou art more lovely and more temperate.
And summer's lease hath all too short a date.
And often is his gold complexion dimmed,
And every fair from fair sometime declines,

This is just a simple implementation of a recursive grep. Next will be me trying to find a way to code this shell script in rust. Hopefully someone will find a use for this code.


Has been tested on OpenBSD 6.5