Grep Recursive and Count

Recursive Grep to show only total matchin count

grep -ro "foo" /some/directory | wc -l | xargs echo "Total matches :"

The -o option of grep prints all the existing occurences of a string in a file.

Grep Recursive and Count

It works for me (it gets the total number of 'string here' found in each file). However, it does not display the total for ALL files searched. Here is how you can get it:

grep -c -r 'string' file > out && \
awk -F : '{total += $2} END { print "Total:", total }' out

The list will be in out and the total will be sent to STDOUT.

Here is the output on the Python2.5.4 directory tree:

grep -c -r 'import' Python-2.5.4/ > out && \
awk -F : '{total += $2} END { print "Total:", total }' out
Total: 11500

$ head out
Python-2.5.4/Python/import.c:155
Python-2.5.4/Python/thread.o:0
Python-2.5.4/Python/pyarena.c:0
Python-2.5.4/Python/getargs.c:0
Python-2.5.4/Python/thread_solaris.h:0
Python-2.5.4/Python/dup2.c:0
Python-2.5.4/Python/getplatform.c:0
Python-2.5.4/Python/frozenmain.c:0
Python-2.5.4/Python/pyfpe.c:0
Python-2.5.4/Python/getmtime.c:0

If you just want to get lines with occurrences of 'string', change to this:

grep -c -r 'import' Python-2.5.4/ | \
awk -F : '{total += $2; print $1, $2} END { print "Total:", total }'

That will output:

[... snipped]
Python-2.5.4/Lib/dis.py 4
Python-2.5.4/Lib/mhlib.py 10
Python-2.5.4/Lib/decimal.py 8
Python-2.5.4/Lib/new.py 6
Python-2.5.4/Lib/stringold.py 3
Total: 11500

You can change how the files ($1) and the count per file ($2) is printed.

How do I recursively grep all directories and subdirectories?

grep -r "texthere" .

The first parameter represents the regular expression to search for, while the second one represents the directory that should be searched. In this case, . means the current directory.

Note: This works for GNU grep, and on some platforms like Solaris you must specifically use GNU grep as opposed to legacy implementation. For Solaris this is the ggrep command.

How can I count all the lines of code in a directory recursively?

Try:

find . -name '*.php' | xargs wc -l

or (when file names include special characters such as spaces)

find . -name '*.php' | sed 's/.*/"&"/' | xargs  wc -l

The SLOCCount tool may help as well.

It will give an accurate source lines of code count for whatever
hierarchy you point it at, as well as some additional stats.

Sorted output:

find . -name '*.php' | xargs wc -l | sort -nr

Recursively counting files in a Linux directory

This should work:

find DIR_NAME -type f | wc -l

Explanation:

  • -type f to include only files.
  • | (and not ¦) redirects find command's standard output to wc command's standard input.
  • wc (short for word count) counts newlines, words and bytes on its input (docs).
  • -l to count just newlines.

Notes:

  • Replace DIR_NAME with . to execute the command in the current folder.
  • You can also remove the -type f to include directories (and symlinks) in the count.
  • It's possible this command will overcount if filenames can contain newline characters.

Explanation of why your example does not work:

In the command you showed, you do not use the "Pipe" (|) to kind-of connect two commands, but the broken bar (¦) which the shell does not recognize as a command or something similar. That's why you get that error message.

Count all occurrences of a string in lots of files with grep

cat * | grep -c string

grep recursive filename matching (grep -ir xyz *.cpp) does not work

Grep will recurse through any directories you match with your glob pattern. (In your case, you probably do not have any directories that match the pattern "*.cpp") You could explicitly specify them: grep -ir "xyz" *.cpp */*.cpp */*/*.cpp */*/*/*.cpp, etc. You can also use the --include option (see the example below)

If you are using GNU grep, then you can use the following:

grep -ir --include "*.cpp" "xyz" .

The command above says to search recursively starting in current directory ignoring case on the pattern and to only search in files that match the glob pattern "*.cpp".

OR if you are on some other Unix platform, you can use this:

find ./ -type f -name "*.cpp" -print0 | xargs -0 grep -i "xyz"

If you are sure that none of your files have spaces in their names, you can omit the -print0 argument to find and the -0 to xargs

The command above says the following: find all files (-type f) under the current directory (./) that match the name glob/wildcard "*.cpp" (-name "*.cpp") and then print them out delimited by a null (-print0). That list of files found should be written to the stdin of the next command: xargs. xargs should read from stdin (default behavior) and split its input on nulls (-0) and then call the grep command with the specified options (grep -i "xyz") on that list of files.

If you are interested in learning more about why grep -ir "xyz" *.cpp does not work the way you think it should, you should search for "shell globbing" (here is a good first article on the subject). I'll also try to provide a quick explanation. When you type in the command grep -ir "xyz" *.cpp and hit enter, there are two programs that are involved in executing your command. The first program is your shell (and unless you've done something to customize things, you are probably usually the bash shell - if you've never heard of a shell or bash, that's where you should start looking, there are tons of good articles). Suffice it say that a shell is just a program that is designed to let you navigate the filesystem on your computer and run other programs. (In Windows, when you double click on an icon to launch a program, or open a folder to access a file, the program that you are running is explorer.exe and it is the Windows graphical shell). So, when you type the command grep -ir "xyz" *.cpp, before grep is run, the shell handles reading your command and does a few things. One of the things is does is expand glob patterns (things like *.txt or [0-9]+.pdf). Like I said, if you want to understand it, go read more about it, but the thing you should take away is that the grep command never sees the *.cpp. What happens is, the shell looks in the current directory for any files or directories with a name that match the pattern *.cpp and then replaces them on the command line BEFORE it runs the grep command. (If it doesn't find anything that matches, then it will leave the *.cpp there and grep will see it, but grep because doesn't normally do glob matching, this doesn't do anything for you).

Alternatively, when you type in grep -ir "xyz" *, what happens is that the shell replaces the * with the name of every file and directory in the current directory (because * matches anything). Let's say you had a directory that contained file1, file2, and dir1, and dir2, then the shell would perform its replacements and then execute a command that looked like this grep -ir "xyz" file1 file2 dir1 dir2, which means grep would search file1 and file2 for a line with the string xyz, and because of the -ir it also search recursively through dir1 and dir2 and search any files found for that string as well. Lastly, if you've followed everything I've said so far, then it will make sense to you that grep does have a way to use glob patterns on recursive searches, and that is to use the --include option, as in the command I described earlier: grep -ir --include "*.cpp" "xyz" ., and the reason why we put the *.cpp in quotes in that command is to prevent the shell from trying to expand the glob pattern before we run the command.

How to count occurrences of a word in all the files of a directory?

grep -roh aaa . | wc -w

Grep recursively all files and directories in the current dir searching for aaa, and output only the matches, not the entire line. Then, just use wc to count how many words are there.

Counting number of occurrences in several files

You can get a recursive listing from find and execute commands with its -exec argument.

I'd suggest like:

find . -name '*.c' -exec cat {} \; | tr -c -d ']' | wc -c

The -c argument to tr means to use the opposite of the string supplied -- i.e. in this case, match everything but ].

The . in the find command means to search in the current directory, but you can supply any other directory name there as well.



Related Topics



Leave a reply



Submit