Get all occurrences of a string within a directory(including subdirectories) in .gz file using bash? - bash

I want to find all the occurrences of "getId" inside a directory which has subdirectories as follows:
*/*/*/*/*/*/myfile.gz
i tried thisfind -name *myfile.gz -print0 | xargs -0 zgrep -i "getId" but it didn't work. Can anyone tell me the best and simplest approach to get this?

find ./ -name '*gz' -exec zgrep -aiH 'getSorById' {} \;
find allows you to execute a command on the file using "-exe" and it replaces "{}" with the file name, you terminate the command with "\;"
I added "-H" to zgrep so it also prints out the file path when it has a match, as its helpful. "-a" treats binary files as text (since you might get tar-ed gzipped files)
Lastly, its best to quote your strings in case bash starts globbing them.
https://linux.die.net/man/1/grep
https://linux.die.net/man/1/find

Use the following find approach:
find . -name *myfile.gz -exec zgrep -ai 'getSORByID' {} \;
This will print all possible lines containing getSORByID substring

Related

Find string inside files and replace with a new string

I need to find all files containing certain text inside my project directory.
This includes sub-directories.
I've managed to find all the files:
find . -type f -exec grep -H 'Rename' {} \;
Now I need to replace the keyword "Rename" with "XYZ" leaving the rest of text in each file intact.
Ideas?
sed instead of grep.
find . -type f -exec sed -i 's/Rename/XYZ/g' {} \;
grep already scans all the lines of every file, so you aren't losing anything. This just makes the change when it finds it, instead of printing out the line.

How to add a line in files recursively bash?

I use the command to add one line at the beginning of the php files in the current directory and its subdirrectories recursively.
find . -name "*.php" -exec sed -i -e "/<?php/a\\
Sometext" *.php \;
But it adds Sometext many times (instead of one) only in php files in the current directory (instead of all). What I did wrong?
You don't pass the files found by find to the sed command, but the files found by the shell glob *.php. Before find is executed, the *.php is expanded and your command becomes
find . -name '*.php' -exec sed ... 1stMatch.php 2ndMatch.php ... \;
Afterwards, find will for each found file execute the command
sed ... 1stMatch.php 2ndMatch.php ...
You probably wanted to write
find . -name '*.php' -exec sed -i -e '/<?php/a\\
Sometext' {} \;
For each file, find executes sed and replaces {} by one file name.
In this case, you could even write {} + instead of {} \; such that sed is executed only once on all files at once, instead of once for every file – this will speed up your command drastically.

using output of grep command to find command

I have a problem related to searching a pattern among several files.
I want to search "Logger." pattern in jsp files,so i used the command
grep -ir Logger. * | find . -name *.jsp
Now the problem i am facing is that this command is listing all the jsp files and its not searching the pattern "Logger." in jsp files and listing them.
I just want the jsp files in which "Logger." instance is present.
start like this
you want to search in jsp files.
find . -name "*.jsp"
the above will output all the jsp files recursively from current directory. like below
1/2/ahbd.jsp
befwej/dg/wefwefw/wefwefwe/ijn.jsp
And now you want to find the string in just these files.
grep -ir Logger. (output of find)
so the actual complete command becomes:
find . -name "*.jsp"|xargs grep -ir 'Logger.'
magic here is done by xargs
it gives the output of find as an input for grep line by line.
if you remove xargs,then only the first line that is 1/2/ahbd.jsp will be searched for the string.
there are several other ways to do this.But i feel more comfortable using this regularly
To recursively find all *.jsp files containing the string Logger. you can do:
find . -type f -name '*.jsp' -exec grep -l "Logger\." {} \;
grep -l means to print only the file name if the file contains the string.
The -exec switch of find will execute the given command for each file matching the other criteria (-type f and -name '*.jsp'). The string {} is substituted by the filename. Some versions of find also support + instead of {} to feed several file names to the command (like xargs does) and not only one at once, e.g.:
find . -type f -name '*.jsp' -exec grep -l "Logger\." + \;
You can just use grep for that, here's a command that should give you the results:
grep -ir "Logger\." * | grep ".jsp"
Problem is, grep will bail when you use ".jsp" instead or "" if you don't have at least one .jsp file into your root directory. So we have to tell him to look every file.
Since you give grep the -r (recursive) argument, it will walk the subdirectories to find the pattern "Logger.", then the second grep will only display the .jsp files. Note that -i tells grep not to care about the letter case, which is may be not what you want.
edit: following John's answer: we have to escape the . to prevent it to be taken as a regexp.
re-edit: actually, I think that using find is better, since it will filter the jsp files directly instead of grepping all the files:
find . -name "*.jsp" -exec grep -i "Logger\." {} \;
(you don't need the -r anymore since find takes care of recursion.
If you have bash 4+
shopt -s globstar
shopt -s nullglob
for file in **/*.jsp
do
if grep -q "Logger." "$file" ;then
echo "found in $file"
fi
# or just grep -l "Logger." "$file"
done

Shell script traversing the all subdirectories and modifying the content of files

I need to modify a number of files inside a directory. I need to modify all those files which contain particular text and have to replace with some new text.
So I thought of writing a shell script which will traverse through all the subdirectories and modify the content but I'm having problem while traversing the all possible directories.
You can use find to traverse through subdirectories looking for files and then pass them on to sed to search and replace for text.
e.g.
find /some/directory -type f -name "*.txt" -print -exec sed -i 's/foo/bar/g' {} \;
will find all txt files and replace foo with bar in them.
The -i makes sed change the files in-place. You can also supply a backup-suffix to sed if you want the files backed up before being changed.
GNU find
find /some_path -type f -name "*.txt" -exec sed -i 's/foo/bar/g' "{}" +;
http://git.savannah.gnu.org/cgit/bash.git/tree/examples/functions/recurse
:)
You want find.
for n in $(find | grep txt$)
do
echo $n
modify_content.sh $n
done

How do I grab the filename of the file containing a certain string when there are hundreds of files?

I have a folder with 200 files in it. We can say that the files are named "abc0" to "abc199". Five of these files contain the string "ez123" but I don't know which ones. My current attempt to find the file names of the files that contain the string is:
#!/bin/sh
while read FILES
do
cat $FILES | egrep "ez123"
done
I have a file that contains the filenames of all files in the directory. So I then execute:
./script < filenames
This is verifies for me that the files containing the string exist but I still don't have the name of the files. Are there any ideas concerning the best way to accomplish this?
Thanks
you can try
grep -l "ez123" abc*
find /directory -maxdepth 1 -type f -exec fgrep -l 'ez123' \{\} \;
(-maxdepth 1 is only necessary if you only want to search the directory and not the tree recursively (if there's any)).
fgrep is a bit faster than grep. -l lists the matched filenames only.
Try
find -type f -exec grep -qs "ez123" {} \; -print
This will use find to find all real files in current directory (and subdirectories), execute grep on them ({} will be replaced by file name, -qs tells it to be silent and just set an exit code), -print will print out the names of the files that grep found a matching line in.
What about:
xargs egrep -l ez123
That reads filenames from stdin and prints out the filenames with matches.

Resources