How can I find, xargs and grep the resulting output? - command-line

I would like to check the 'code rating' for each Python file in a directory. The name of the file and its rating should be printed.
I thought the following would at least print all code ratings:
find . -name '*.py' -print0 | xargs -0 pylint | grep "has been rated"
However, it prints only one code rating. Why? How do I fix it?

Try:
find . -name '*.py' -exec pylint {} \; | grep "has been rated"

Related

find + xargs + cat does not work with --name argument

I'm trying to concatenate all the files of a that ends with coref extension.
This works (but add unwanted files):
find ../corpus/dev/txt/ | xargs cat
This not works.
find ../corpus/dev/txt/ -name '*.coref' | xargs cat
In the second comand find returns 1566 results but xrags cat does nothing.
Why the -name arguments mess it all?
Try to use -print0 like this:
find ../corpus/dev/txt/ -name '*.coref' -print0 | xargs -0 cat
if you find to many files and the xargs list gets too long, you can try this:
find ../corpus/dev/txt/ -name '*.coref' -print0 | xargs -n1 -0 cat >> /tmp/file

Linux: Using find and grep to find a keyword in files and count occurrences

I'm using executing this bash commands inside a search script I've built with php:
find myFolder -type f -exec grep -r KEYWORD {} +
find myFolder -type f -exec grep -r KEYWORD {} + | wc -l
find myFolder -type f | wc -l
The first line gives me back the filenames where KEYWORD was found.
The second line gives me the number of occurrences and the third line the total number of files.
Is there a way to do this more elegantly and faster?
You can get more efficiency if you avoid -exec, which makes one fork per file match. xargs is a better choice here. So I would do something like this:
find myFolder -type f -print0 | xargs -0 grep KEYWORD
find myFolder -type f -print0 | xargs -0 grep KEYWORD | wc -l
The last one should be OK, at least with GNU find.
The -print0 and -0 ensure that filenames with spaces in them are handled correctly.
Note that grep -r` implies recursive grepping, but as you're only supplying one filename in each invocation it is redundant.

find using multiple name patterns

I have this working fine for me:
find Sources/$1-$2 -name '*' |xargs perl -pi -e "s/domain.com/$2/g"
But when I change it to the following it doesn't:
find Sources/$1-$2 -name '*.php,*.rb' |xargs perl -pi -e "s/domain.com/$2/g"
What wrong?
Here's some explanation behind the solution that others have provided.
The tests in a find command are combined with Boolean operators:
-a -and
-o -or
! -not
If you don't supply an operator, -and is the default.
find . -type f -name '*.rb' # The command as entered.
find . -type f -a -name '*.rb' # Behind the scenes.
Your search failed because it didn't find any matching files:
# Would find only files with bizarre names like 'foo.php,bar.rb'
find . -name '*.php,*.rb'
You need to supply the file extensions as separate -name tests, combined in an OR fashion.
find . -name '*.php' -o -name '*.rb'
you have to write it as:
find Sources/$1-$2 -name '*.php' -o -name '*.rb' ....
I'm guessing that you want all files then end in .php and .rb.
Try find Sources/$1-$2 \( -iname "*.php" -o -iname "*.rb" \) -print |xargs perl -pi -e "s/domain.com/$2/g"
It is much better filtering out find's result with [ef]grep. Why?
Because you can fed the grep pattern as an argument, or can read it from the config or soo. It is much easier to write: grep "$PATTERN" as constructing long find arguments with '-o'. (ofc, here are situations, where find args are better), but not in your case.
The cost is one more process. So, for you example is easy to write a script myscript.sh
find Sources/$1-$2 -print | egrep -i "$3" | xargs ...
you can call it
./myscript.sh aaa bbb ".(php|rb)$"
and the result will equivalent to more complicated
find Sources/$1-$2 \( -iname '*.php' -o -iname '*.rb' \) | xargs ...
but
why bother? If you have bash4+, (and shopt -s globstar in your .bashrc) you can simple write:
perl -pi -e '.....' Sources/aaa-bbb/**/*.{rb,php}
the ** is like a find -name.
By the way, xargs is not needed here.
find Sources/$1-$2 \( -name '*.php' -o -name '*.rb' \) \
-exec perl -i -pe "s/domain\.com/$2/g" {} +
Also notice the "." in /domain.com/ needs to be escaped.

Why does "find . -name *.txt | xargs du -hc" give multiple totals?

I have a large set of directories for which I'm trying to calculate the sum total size of several hundred .txt files. I tried this, which mostly works:
find . -name *.txt | xargs du -hc
But instead of giving me one total at the end, I get several. My guess is that the pipe will only pass on so many lines of find's output at a time, and du just operates on each batch as it comes. Is there a way around this?
Thanks!
Alex
How about using the --files0-from option to du? You'd have to generate the null-terminated file output appropriately:
find . -name "*txt" -exec echo -n -e {}"\0" \; | du -hc --files0-from=-
works correctly on my system.
find . -print0 -iname '*.txt' | du --files0-from=-
and if you want to have several different extensions to search for it's best to do:
find . -type f -print0 | grep -azZEi '\.(te?xt|rtf|docx?|wps)$' | du --files0-from=-
The xargs program breaks things up into batches, to account for the limits due to the maximum length of a unix command line. It's still more efficient than running your subcommand one at a time but, for a long list of inputs, it will run the command enough times that each "run" is short enough that it won't cause issues.
Because of this, you're likely seeing one output line per "batch" that xargs needs to run.
Because you may find it useful/interesting, the man page can be found online here: http://unixhelp.ed.ac.uk/CGI/man-cgi?xargs
One other thing to note (and this may be a typo in your post or my misunderstanding) is that you have the "*.txt" unescaped/quoted. Ie, you have
find . -name *.txt | xargs du -hc
where you probably want
find . -name \*.txt | xargs du -hc
The difference being that the command line may be expanding the * into the list of filenames that match... rather than passing the * into find, which will use it as a pattern.
Another simple solution:
find . -name *.txt -print0 | xargs -0 du -hc
One alternate solution is to use bash for loop:
for i in `find . -name '*.txt'`; do du -hc $i | grep -v 'total'; done
This is good for when you need more control of what happens in the loop.
xargs busts its input into reasonable-sized chunks - what you're seeing are totals for each of those chunks. Check the man page for xargs on ways to configure its handling of input.
One alternate solution is to use awk:
find . -name "*.txt" -exec ls -lt {} \; | awk -F " " 'BEGIN { sum=0 } { sum+=$5 } END { print sum }'

using find command to search for all files having some text pattern

I use following find command to find and show all files having the input text pattern.
find . -type f -print|xargs grep -n "pattern"
I have many project folders each of which has its own makefile named as 'Makefile'.(no file extension, just 'Makefile')
How do i use above command to search for a certain pattern only in the files named Makefile which are present in all my project folders?
-AD.
-print is not required (at least by GNU find implementation). -name argument allows to specify filename pattern. Hence the command would be:
find . -name Makefile | xargs grep pattern
If you have spaces or odd characters in your directory paths youll need to use the null-terminated method:
find . -name Makefile -print0 | xargs -0 grep pattern
find . -type f -name 'Makefile' | xargs egrep -n "pattern"
use egrep if you have very long paths
Duplicate of : this
You can avoid the use of xargs by using -exec:
find . -type f -name 'Makefile' -exec egrep -Hn "pattern" {} \;
-H on egrep to output the full path to the matching files.
grep -R "string" /path
Please find this link
http://rulariteducation.blogspot.in/2016/03/how-to-check-particluar-string-in-linux.html
you can use ff command i.e ff -p .format. For eg ff -p *.txt
Find big files occupying large disk space
we need to combine multiple command .
find . -type f | xargs du -sk | sort -n | tail;