특정 파일 형식에서 단어를 찾는 재귀 grep

특정 파일 형식에서 단어를 찾는 재귀 grep

파일 시스템의 모든 쉘 스크립트에서 특정 단어를 검색하는 명령줄 명령이 필요했기 때문에 직장에서 요청하여 다음과 같은 해결책을 얻었습니다.

grep word `find / -name \*.sh 2>/dev/null`
find / -name "*.sh" 2>/dev/null | xargs grep word

그러나 저는 명령줄에 익숙하지 않기 때문에 두 솔루션 모두 투명해 보이지 않습니다. 나는 다음과 같은 작업을 선호합니다.

ls -r *.sh | cat | grep -H word

하지만 파일 이름을 cat으로 파이프할 수는 없는 것 같습니다(적어도 그게 문제라고 생각합니다).

가장 명확한 해결책은 무엇입니까? 둘째, 가장 효율적인 솔루션은 무엇입니까?

편집: 스크립트를 수정할 수 있도록 어떤 파일에서 단어가 발견되었는지 알아야 합니다.

답변1

편집하다:GNU 유틸리티가 있는 경우 다음을 참조하세요.자일스의 대답grep이보다 GNU의 재귀 기능을 사용하는 훨씬 간단한 방법이 있습니다 find. 파일 이름만 표시하려면 -l아래에 설명된 옵션을 추가해야 합니다.


grep -l word일치하는 파일의 이름만 인쇄하는 데 사용됩니다 .

파일 .sh시스템 에서 /.find

가장 이식 가능하고 효과적인 조언은 다음과 같습니다.

find / -type f -name '*.sh' -exec grep -l word {} + 2>/dev/null

각 구성 요소의 의미를 이해하면 거의 읽기 쉽고 구문 분석이 어렵지 않습니다.

  • find /: find파일 시스템의 루트 디렉터리에서 실행합니다./
  • -type f: 일반 파일만 일치합니다.
  • -name '*.sh': ...그리고 이름이 다음으로 끝나는 파일만 일치합니다..sh
  • -exec ... {} +...: 그룹의 일치하는 파일에 대해 지정된 명령을 실행하고 {}그룹의 파일 이름으로 바꿉니다. 아이디어는 system() 의 한도 내에서 한 번에 많은 파일에 대해 명령을 실행하는 것입니다 ARG_MAX. 양식의 효율성은 각 호출에 전달되는 파일 수를 최대화하여 명령을 호출해야 하는 횟수를 최소화하는 {} +데서 비롯됩니다 .......
  • grep -l word {}: 여기서 위와 {}같이 반복 {}되고 파일 이름으로 대체됩니다. 앞서 언급했듯이 grep -l인쇄에는 word.
  • 2>/dev/null: 오류 메시지를 숨깁니다(기술적으로 표준 오류를 블랙홀로 리디렉션 /dev/null). 이는 심미적 및 실용적인 이유 때문입니다. 이를 실행하면 많은 "권한 거부" 메시지가 나타날 find수 있고 읽기 권한이 없는 파일과 탐색 권한이 없는 디렉토리에 대해 신경 쓰지 않을 수 있기 때문입니다./

귀하가 질문에 받아 게시한 조언에 몇 가지 문제가 있습니다. 둘 다

grep word `find / -name \*.sh 2>/dev/null

그리고

find / -name "*.sh" 2>/dev/null | xargs grep word

이름에 공백이 있는 파일은 실패합니다. 파일 이름 전체를 명령 대체에 포함시키지 않는 것이 가장 좋습니다. 첫 번째는 ARG_MAX 제한과 관련하여 추가 문제가 발생할 가능성이 있습니다. 두 번째는 내 제안에 가깝지만 xargs여기에서 사용할 이유가 없습니다 . 안전하고 올바른 사용을 위해서는 xargsGNU 전용 옵션( find -print0 | xargs -0)에 대한 일부 이식성을 희생해야 한다는 점은 말할 것도 없습니다.

답변2

비임베디드 Linux, Cygwin 또는 기타 시스템GNU grep, 존재하다FreeBSD, 존재하다네트워크BSD그리고OSX:

grep -r --include='*.sh' word .

출력을 구문 분석하지 않습니다.ls. 그리고 출력에 find다음과 같은 명령 대체를 사용하지 마십시오.jw013은 설명했다.

답변3

grepfind많은 경우 및 의 조합 은 ack(betterthangrep.com):

ack [OPTION]... PATTERN [FILE]

귀하의 예를 들어,

ack --shell word /

노트

ack

  • 재귀적으로 검색하지만(기본적으로)
  • .git, .hg, .svn... 와 같은 일반적인 버전 제어 시스템의 (기본) 디렉터리를 무시합니다.
  • 일반적인 파일 형식에 대한 필터를 사용하여 결과 범위를 쉽게 좁힐 수 있습니다(다양한 파일 이름 패턴은 아래 참조).
  • "대소문자 무시" 등과 grep같은 유사한 구문과 동일/유사 매개변수 가 있습니다 .-i
  • ack-grep시스템에서 호출 될 수 있습니다 (제 기억이 맞다면 데비안 기반 배포판에서).

파일 이름 패턴

이 옵션은 --shell축약되어 있으며 다음 과 같은 --type=shell여러 파일 형식을 다룹니다..sh .bash .csh .tcsh .ksh .zsh

ack --help-types

파일 만 원하는 경우 .sh고유한 유형을 정의(추가) 하고 다음과 같이 sh이 필터( )를 사용해야 합니다.--sh

ack word --type-add=sh=.sh --sh /

다소 복잡해 보이지만 .sh아래 파일을 재귀적으로 검색할 수 있습니다 /. 로컬 검색의 경우(예를 들어 시작 디렉터리를 지정하지 않고 \) 더 쉬울 것입니다.

ack word *.sh

관련 정보