Linux: Locate a file by name and then search for a specific word inside

If you’ve ever needed to locate a file by name and then search for a specific word inside it, then this blog is for you.
Linux makes it simple by combining two powerful tools: find and grep:

# find /your/path -type f -name "*.log" -exec grep -i "error" {} +

Explanation:

  • -type f: Filters for files only.
  • -name "*.log": Limits the search to .log files.
  • -exec grep -i "error" {} +: Searches for the word "error" inside each found file, ignoring case sensitivity.

In my case, I was searching for files named flashgrid_node and then wanted to find content containing the keyword “SYNCING“. Here is my command version:

# find ./ -type f -name "flashgrid_node" -exec grep -i "SYNCING" {} +

It searches in the current directory (‘./’).

Useful tip, If you want to show only the file names that contain the word, you can add the -l flag to grep:

# find /your/path -type f -name "*.log" -exec grep -il "error" {} +

This was my output:

$ find ./ -type f -name "flashgrid_node" -exec grep -il "SYNCING" {} +

./rac1/rac1.example.com/flashgrid_node
./rac2/rac2.example.com/flashgrid_node
./racq/racq.example.com/flashgrid_node

Rename directories, subdirectories, files recursively that contain matching string

Problem:

I have copied /u01 directory (containing Oracle software) from another node. The Oracle software home includes directories and files with hostnames.

My task was to rename all directories, subdirectories, and files containing the specific hostname (in my case rac2) into rac1.

Let me show you the folder hierarchy that is challenging when you want to rename by script. For simplicity, this hierarchy is made up, but this type of dependency exists in /u01:

/u01/first_level_rac2/second_level_rac2/third_level_rac2.txt

We want to have:

/u01/first_level_rac1/second_level_rac1/third_level_rac1.txt

So finally, all folders or files containing the string rac2 should be replaced with rac1.

The challenge here is that you need to start renaming from the third_level, then rename second_level and later first_level. Otherwise, you will have accessibility issues with other subdirectories or files.

Solution:

If you want a shortcut, here is the code:

[root@rac1 ~]# find /u01 -depth -name "*rac2*" | while read i ; do
newname="$(echo ${i} |sed 's/\(.*\)rac2/\1rac1/')" ;
echo "mv" "${i}" "${newname}" >> rename_rac2_rac1.sh;
done

Later you need to run rename_rac2_rac1.sh file, which will contain mv statements for each matching file or folder.

Let me explain,

find /u01 -depth -name "*rac2*" – This will find all files and folders that contain rac2 keyword and will display the output with depth-first order.

Without depth, the output is the following:

/u01/first_level_rac2
/u01/first_level_rac2/second_level_rac2
/u01/first_level_rac2/second_level_rac2/third_level_rac2.txt

With -depth, you will see the next order:

/u01/first_level_rac2/second_level_rac2/third_level_rac2.txt
/u01/first_level_rac2/second_level_rac2
/u01/first_level_rac2

"$(echo ${i} |sed 's/\(.*\)rac2/\1rac1/')" – In this line, the value of i iterator (each line from find command) will be redirected to sed command that will replace the first occurrence of rac2 keyword searching from backward.

Later old name and a new name will be concatenated with mv statement and saved into rename_rac2_rac1.sh

This will be mv statements generated by the script:

mv /u01/first_level_rac2/second_level_rac2/third_level_rac2.txt /u01/first_level_rac2/second_level_rac2/third_level_rac1.txt

mv /u01/first_level_rac2/second_level_rac2 /u01/first_level_rac2/second_level_rac1

mv /u01/first_level_rac2 /u01/first_level_rac1