1

I am intending to print all the lines with their line numbers along with its location within a specific directory which matches a particular string

Example..

/home/some_dir/file.txt -(LineNo) -(printing_thatlineitself)

I currently have 2 commands with me but both have some shortcomings

find /home/some_dir -type f -exec grep -Hn "Text To Find" {} \;

This above find command seems to work accurately but the issue is that it works quite slow

find /home/some_dir -type f -print0 | xargs -0 grep -Hn -C2 "Text To Find"

This command works comparatively quite faster but it provides inaccurate results. It even prints those lines where my inputted string is not present at all

Can someone provide a solution that works accurately and is fast as well? PS / its fine if the solution doesn't use the find command to achieve this .it just has to be something I can directly run in CLI

Aman Chourasiya
  • 1,078
  • 1
  • 10
  • 23
Sachin
  • 1,217
  • 2
  • 11
  • 31
  • 2
    `-C2` is present in second command but not first... to make first one run faster, use `{} +`... if your content is ASCII, use `LC_ALL=C grep` to get even faster result.. another suggest is to use [ripgrep](https://github.com/BurntSushi/ripgrep) instead of find+grep – Sundeep Sep 03 '20 at 15:23
  • 2
    `grep` can search recursively on its own, try `grep -IHnr "my regex" /home/some_dir/`. If you want to find a simple text you can use `-F` too which indicates you're looking for fixed string not regex. – János Roden Sep 03 '20 at 15:27
  • `grep -IHnr "Text to find" .` is the robust and fast way to do this job.- – thanasisp Sep 04 '20 at 19:42
  • It is probably not actually true that the `xargs` solution is faster, though it may start printing results sooner under some conditions. – tripleee Sep 07 '20 at 18:34

2 Answers2

4

As suggested in the comments , grep can be used to do this very efficiently

grep -IHnr "Text to find" .

-I : Process a binary file as if it did not contain matching data (to exclude binary files)

-H : Print the filename for each match

-n : Display the matched lines and their line numbers

-r : Recursively search subdirectories listed

"Text to find" : Search string

. : Directory for search (current directory)

thanasisp
  • 5,855
  • 3
  • 14
  • 31
Sachin
  • 1,217
  • 2
  • 11
  • 31
0

I would not squeeze everything into one command. It is simpler to write a small shell script which combines several utilities. For example,

$ cat script.sh
#!/bin/sh   
IFS='
'
for i in `find . -type f`
do
    awk '
    /Text To Find/ {
        print FILENAME, NR
    }' "$i"
done
$ chmod +x script.sh
$ ./script.sh 
./script.sh 7
slitvinov
  • 5,693
  • 20
  • 31
  • 1
    Copy/paste that script into http://shellcheck.net and/or see https://mywiki.wooledge.org/BashFAQ/001 and http://mywiki.wooledge.org/BashFAQ/082 for some issues. – Ed Morton Sep 03 '20 at 17:38
  • sh != bash, https://stackoverflow.com/a/5725402/1534218 – slitvinov Sep 03 '20 at 17:48
  • /bin/sh could be (and probably is these days) aliased to /bin/bash on any given system. In any case, shellcheck takes your shell into consideration and the issues I'm referring to apply in any bourne-like shell. – Ed Morton Sep 03 '20 at 17:51