파일 시스템의 모든 쉘 스크립트에서 특정 단어를 검색하는 명령줄 명령이 필요했기 때문에 직장에서 요청하여 다음과 같은 해결책을 얻었습니다.
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
여기에서 사용할 이유가 없습니다 . 안전하고 올바른 사용을 위해서는 xargs
GNU 전용 옵션( find -print0 | xargs -0
)에 대한 일부 이식성을 희생해야 한다는 점은 말할 것도 없습니다.
답변2
비임베디드 Linux, Cygwin 또는 기타 시스템GNU grep, 존재하다FreeBSD, 존재하다네트워크BSD그리고OSX:
grep -r --include='*.sh' word .
출력을 구문 분석하지 않습니다.ls
. 그리고 출력에 find
다음과 같은 명령 대체를 사용하지 마십시오.jw013은 설명했다.
답변3
grep
find
많은 경우 및 의 조합 은 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