I am attempting to write a bash
script that searches contents of files in a specified directory tree for the presence of a specified substring.
Using grep
's recursive function alone is not sufficient, since I potentially need to iterate over the /
directory (and all sub-directories) of a system, which makes grep
run out of memory and abort. Therefore I decided to get a list of all directories and sub-directories in the specified directory tree using find
with the following variables denoting arguments passed to the script.
searchdir=$HOME # passed in a script argument
searchstr="secret" # passed in a script argument
I call the find
utility and store the output into a temporary file.
TF=$(mktemp)
find ${searchdir} -type d 1>$TF 2>/dev/null
With the list of all directories in the temporary file, I proceed to iterate over the lines of this file using a while-do
loop with the intention to perform a search over all files in each directory. For grep
, I use the format of parameters provided in this answer to search all files, including the hidden ones, in the single directory.
cat $TF | while read line || [[ -n $line ]];
do
grepdir="${line}/{*,.*}"
grep -sHn "${searchstr}" ${grepdir}
done
... however, that code produces no output.
I verified that...
The ${TF}
does contain the correct list of all directories. Outputting the ${grepdir}
variable gives the output I'm expecting to find.
/home/user/{*,.*}
/home/user/.ssh/{*,.*}
/home/user/test/{*,.*}
# ... and so on
If I run the grep
command with a hardcoded directory, particularly the ~/test/
directory, which contains two test files with the string it's supposed to find
grep -sHn "${searchstr}" /home/user/test/{*,.*}
... it correctly outputs the two files containing the substring "secret".
/home/user/test/asdf:7:secret
/home/user/test/test.txt:5:asdfasfdsecretaasdfafd
A format that works for me is the one originally mentioned in the answer discussing the recursive use of grep
. If I do this:
cat $TF | while read line || [[ -n $line ]];
do
grep -rn "${line}" -e "${searchstr}"
done
... I get some output (technically correct, but with many duplicate entries), but since the grep
is processing the directories recursively and I have a list of all directories, I am bound to get the same results many times and on directories such as the aforementioned root directory, grep
will fail entirely, which is what I'm trying to avoid.
I should also probably mention that my desperate hacks to get it working, such as passing $(echo "${grepdir}")
as the parameter, led to no results as well.
There is most likely a misconception in my thinking or understanding of bash
. Shouldn't bash
expand the ${grepdir}
variable before making a call to grep
? Where is my script going wrong?
-s
from yourgrep
command, I suspect you will see a bunch of error messages like/home/user/{*,.*}: No such file or directory
- is that the case? – steeldriver Nov 25 '19 at 18:36