패턴을 찾은 상태에서만 파일 이름 찾기 및 반향


16

나는 이것을 많이 사용했으며, 달성하려는 개선점은 grep에서 일치하지 않는 에코 파일 이름을 피하는 것입니다. 더 좋은 방법은?

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

답변:


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

일치하는 줄 뒤에 파일 이름 인쇄합니다 .

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

모든 일치하는 라인의 앞에 파일 이름을 인쇄 할 것이다 (우리는 추가 /dev/null단지 거기 어디에 경우에 대해 하나 같이 일치하는 파일 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 및 파생 상품에서도 작동합니다).


6

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고급 술어가 더 필요한 경우 에만 필요 합니다.


1
GNU의 버전에 따라 grep, grep또는 디렉토리에 대한 심볼릭 링크 또는 이송 심볼릭 링크 내에서 볼 수도 있고 보지 않을 수도 있습니다. 다른 유형의 비정규 파일 처리에 약간의 변형이있을 수도 있습니다.
Stéphane Chazelas

5

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

1

다음과 같은 것을 시도해 볼 수 있습니다.

find . -name "*.py:" -exec grep -l {} \;

find 명령 및 표준 find 명령 기능으로 발견 된 모든 파일에 대한이 exec grep 명령


1

-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

1

있습니다 grep기본 출력으로 형식에서의 결과는 당신이 원하는 대안. 내가 아는 가장 인기있는 것은 ag(실버 검색 자)와 ack입니다. ag보다 빠른 대안으로 광고됩니다 ack.

$ ag '^\w+\s*\w+\(' ~/build/i3/src
build/i3/src/display_version.c
58:void display_running_version(void) {

build/i3/src/load_layout.c
42:static TAILQ_HEAD(focus_mappings_head, focus_mapping) focus_mappings =
518:json_content_t json_determine_content(const char *filename) {
575:void tree_append_json(Con *con, const char *filename, char **errormsg) {

build/i3/src/x.c
64:CIRCLEQ_HEAD(state_head, con_state) state_head =
67:CIRCLEQ_HEAD(old_state_head, con_state) old_state_head =
70:TAILQ_HEAD(initial_mapping_head, con_state) initial_mapping_head =
97:void x_con_init(Con *con, uint16_t depth) {
...

나는 여기에 당신을 보여줄 수 없지만 출력물은 깔끔하게 채색됩니다. 나는 올리브 녹색으로 파일 이름을 얻었고, 줄 번호는 금색으로, 각 줄에서 일치하는 부분은 붉은 색으로 나타납니다. 색상은 사용자 정의 할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.