패턴이 발견된 파일 이름만 찾아 에코합니다.

패턴이 발견된 파일 이름만 찾아 에코합니다.

나는 이것을 많이 사용하며 내가 달성하려는 개선은 grep에서 일치하지 않는 파일 이름이 에코되는 것을 방지하는 것입니다. 이 작업을 수행하는 더 좋은 방법은 무엇입니까?

    for file in `find . -name "*.py"`; do echo $file; grep something $file; done

답변1

find . -name '*.py' -exec grep something {} \; -print

파일 이름을 인쇄합니다뒤쪽에일치하는 라인.

find . -name '*.py' -exec grep something /dev/null {} +

일치하는 각 줄 앞에 파일 이름을 인쇄합니다( /dev/null우리가 추가한 경우는하나찾을 파일만 전달하는 경우 file as와 일치하면 grep파일 이름이 인쇄되지 않습니다. GNU 구현에는 대안으로 옵션이 grep있습니다 -H.

find . -name '*.py' -exec grep -l something {} +

적어도 하나의 일치하는 줄이 있는 파일의 파일 이름만 인쇄합니다.

파일 이름 인쇄앞으로줄을 일치시키려면 대신 awk를 사용할 수 있습니다.

find . -name '*.py' -exec awk '
  FNR == 1 {filename_printed = 0}
  /something/ {
    if (!filename_printed) {
      print FILENAME
      filename_printed = 1
    }
    print
  }' {} +

또는 각 파일에 대해 두 번 호출합니다 . 각 파일에 대해 최소 하나의 명령과 최대 두 개의 명령을 grep실행하고 파일 내용을 두 번 읽으므로 효율성은 떨어집니다 .grep

find . -name '*.py' -exec grep -l something {} \; \
                    -exec grep something {} \;

어떤 경우 에라도,find그런 식으로 출력을 반복하고 싶지는 않습니다.그리고변수를 인용하는 것을 잊지 마세요.

GNU 도구와 함께 쉘 루프를 사용하려면 다음을 수행하십시오.

find . -name '*.py' -exec grep -l --null something {} + |
   xargs -r0 sh -c '
     for file do
       printf "%s\n" "$file"
       grep something < "$file"
     done' sh

(FreeBSD 및 그 파생물에도 적용됩니다).

답변2

출력에 파일 이름을 포함하도록 grep에 지시할 수 있습니다. 따라서 일치하는 항목이 있으면 콘솔에 표시됩니다. 파일에 일치하는 항목이 없으면 파일에 대한 줄이 인쇄되지 않습니다.

find . -name "*.py" | xargs grep -n -H something

에서 man grep:

-H       Always print filename headers with output lines
-n, --line-number
         Each output line is preceded by its relative line number in the file, starting at line 1.  The line number counter is reset for each file processed.
         This option is ignored if -c, -L, -l, or -q is specified.

파일 이름에 공백이 포함될 수 있는 경우 NUL 문자를 구분 기호로 사용하도록 파이프를 전환해야 합니다. 이제 전체 명령은 다음과 같습니다.

find . -name "*.py" -print0 | xargs -0 grep -n -H something

답변3

GNU grep을 사용하는 경우 해당 -r또는 --recursive옵션을 사용하여 다음과 같은 간단한 찾기를 수행할 수 있습니다.

grep -r --include '*.py' -le "$regexp" ./ # for filenames only
grep -r --include '*.py' -He "$regexp" ./ # for filenames on each match

find더 고급 술어가 필요한 경우에만 필요합니다.

답변4

인수를 사용하십시오 -l.

for file in `find . -name "*.py"`; do grep -l something $file && grep something $file; done

더 흥미로운 사용법은 다음과 같습니다.

for file in $(find . -name '*.py' -exec grep -l something '{}' +); do echo "$file"; grep something $file; done

관련 정보