find tekst in files in subfolders - linux

So this question might have been asked before, but after some hours of searching (or searching wrongfully) I decided to ask this question.
If it's already been answered before, please link me the question and close this one.
here's my issue.
I have a folder on my filesystem, ie "files". this folder has got a lot of subfolders, with their subfolders. some levels deep, they all have a file which is called the same in all folders. In that file, a lot of text is in it, but it's not ALL the same. I need to have a list of files that contains a certain string.
I KNOW I can do this with
find ./ -type f -exec grep -H 'text-to-find-here' {} \;
but the main problem is: it will get over every single file on that filesystem. as the filesystem contains MILLIONS of files, this would take up a LONG time, specially when I know the exact file this piece of text should be in.
visually it looks like this:
foobar/foo/bar/file.txt
foobar/foobar/bar/file.txt
foobar/barfoo/bar/file.txt
foobar/raboof/bar/file.txt
foobar/oof/bar/file.txt
I need a specific string out of file.txt (if that string exists..)
(and yes: the file in /bar/ is ALLWAYS called file.txt...)
Can anyone help me on how to do so? i'm breaking my head on an "easy" solution :o
Thnx,
Daniel

Use the -name option to filter by name:
find . -type f -name file.txt -exec grep -H 'text-to-find-here' {} +
And if it's always in a directory named bar, you can use -path with a wildcard:
find . -type f -path '*/bar/file.txt' -exec grep -H 'text-to-find-here' {} +

With single GNU grep command:
grep -rl 'pattern' --include=*file.txt
--include=glob
Search only files whose name matches glob, using wildcard

Related

Mass Find/Replace within files having specific filename under command line

I am looking for a quick command to search all .htaccess files for a specific IP address and change it to another IP address from the command line
something like
grep -rl '255.255.254.254' ./ | xargs sed -i 's/254/253/g'
I know the above example is a bad way to do it, just an example (and showing I did some searching to find a solution
Search: files with filename .htaccess (within 2 levels deep of current path?)
Find: 255.255.254.254
Replace with: 255.255.253.253
or, is this too much to ask of my server and I would be better off replacing them as I find them?
Try:
find . -type f -name '.htaccess' -execdir sed -i 's/255\.255\.254\.254/255.255.253.253/g' {} +
How it works:
find .
Start looking for files in the current directory.
-type f
Look only for regular files.
-name '.htaccess'
Look only for files named .htaccess.
-execdir sed -i 's/255\.255\.254\.254/255.255.253.253/g' {} +
For any such files found, run this sed command on them.
Because . is a wildcard and you likely want to match only literal periods, we escape them: \.
We use -execdir rather than the older -exec because it is more secure against race conditions.

"find" specific contents [linux]

I would like to go through all the files in the current directory (or sub-directories) and echoes me back the name of files only if they contain certain words.
More detail:
find -type f -name "*hello *" will give me all file names that have "hello" in their names. But instead of that, I want to search through the files and if that file's content contains "hello" then prints out the name of the file.
Is there a way to approach this?
You can use GNU find and GNU grep as
find /path -type f -exec grep -Hi 'hello' {} +
This is efficient in a way that it doesn't invoke as many grep instances to as many files returned from find. This works in an underlying assumption that find returns a set of files for grep to search on. If you are unsure if the files may not be available, as a fool-proof way, you can use xargs with -r flag, in which case the commands following xargs are executed only if the piped commands return any results
find /path -type f | xargs -r0 grep -Hi 'hello'

Copy specific files recursively

This problem has been discussed extensively but I couldn't find a solution that would help me.
I'm trying to selectively copy files from a directory tree into a specific folder. After reading some Q&A, here's what I tried:
cp `find . -name "*.pdf" -type f` ../collect/
I am in the right parent directory and there indeed is a collect directory a level above. Now I'm getting the error: cp: invalid option -- 'o'
What is going wrong?
To handle difficult file names:
find . -name "*.pdf" -type f -exec cp {} ../collect/ \;
By default, find will print the file names that it finds. If one uses the -exec option, it will instead pass the file names on to a command of your choosing, in this case a cp command which is written as:
cp {} ../collect/ \;
The {} tells find where to insert the file name. The end of the command given to -exec is marked by a semicolon. Normally, the shell would eat the semicolon. So, we escape the semicolon with a backslash so that it is passed as an argument to the find command.
Because find gives the file name to cp directly without interference from the shell, this approach works for even the most difficult file names.
More efficiency
The above runs cp on every file found. If there are many files, that would be a lot of processes started. If one has GNU tools, that can be avoided as follows:
find . -name '*.pdf' -type f -exec cp -t ../collect {} +
In this variant of the command, find will supply many file names for each single invocation of cp, potentially greatly reducing the number of processes that need to be started.

Copy files matching a name in different folders

I am using
find ../../ -type f -name <filename>*.PDF -print0 | xargs -0 cp --target-directory=Directory name with path>;
but it is copy only one file. It doesn't copy all files which is having same name. I need number of files to be searched and copied which is having same name but it it created on different date and different folder. how to solve this issue. I have already created lot's more I am facing the problem in this regard.
This will give you the duplicate files. Once you have the name, you can find them and delete them using your script:
for i in `find .|grep pom.xml`; do
basename $i;
done |sort|uniq -c|sort -n|cut -b9-
PS: everyone's in a hurry. Adding urgency to your posts is usually frowned upon in StackOverflow, and you might prompt the opposite reaction

Find in Linux combined with a search to return a particular line

I'm trying to return a particular line from files found from this search:
find . -name "database.php"
Each of these files contains a database name, next to a php variable like $dname=
I've been trying to use -exec to execute a grep search on this file with no success
-exec "grep {\}\ dbname"
Can anyone provide me with some understanding of how to accomplish this task?
I'm running CentOS 5, and there are about 100 database.php files stored in subdirectories on my server.
Thanks
Jason
You have the arguments to grep inverted, and you need them as separate arguments:
find . -name "database.php" -exec grep '$dbname' /dev/null {} +
The presence of /dev/null ensures that the file name(s) that match are listed as well as the lines that match.
I think this will do it. Not sure if you need to make any adjustments for CentOS.
find . -name "database.php" -exec grep dbname {} \;
I worked it out using xargs
find . -name "database.php" -print | xargs grep \'database\'\=\> > list_of_databases
Feel free to post a better way if you find one (or what some rep for a good answer)
I tend to habitually avoid find because I've never learned how to use it properly, so the way I'd accomplish your task would be:
grep dbname **/database.php
Edit: This command won't be viable in all cases because it can potentially generate a very long argument list, whereas find executes its command on found files one by one like xargs. And, as I noted in my comment, it's possibly not very portable. But it's damn short ;)

Resources