디렉터리를 Grep하고 줄 번호가 포함된 목록을 반환합니다.

디렉터리를 Grep하고 줄 번호가 포함된 목록을 반환합니다.

저는 현재 bash 스크립팅과 이 모든 재미있는 것들에 대해 더 많이 배우려고 노력 중이며 다음과 같은 작은 명령을 함께 엮었습니다.

find $path | xargs grep -n $pattern | awk '{print $1}'

이것이 작동하는 동안 바퀴를 다시 발명하고 있는지 궁금합니다. 디렉토리를 검색하고, 파일에서 패턴을 찾고, 줄 번호가 포함된 목록을 반환하는 더 좋은 방법이 있습니까?

답변1

많은 grep변형이 재귀 옵션을 구현합니다. 예를 들어, GNU grep

-R, -r, --recursive
          Read all files under each directory, recursively; this is equivalent to the -d recurse option.

그런 다음 다음을 삭제할 수 있습니다 find.

grep -n -r $pattern $path | awk '{ print $1 }'

그러나 이는 단순한 행 번호 이상의 것을 보존합니다. awk첫 번째 열을 인쇄합니다. 이 예

src/main/package/A.java:3:import java.util.Map;
src/main/package/A.java:5:import javax.security.auth.Subject;
src/main/package/A.java:6:import javax.security.auth.callback.CallbackHandler;

다음과 같이 인쇄됩니다.

src/main/package/A.java:3:import
src/main/package/A.java:5:import
src/main/package/A.java:6:import

:import각 줄에 주의하세요 . 이를 사용하여 sed출력을 필터링 할 수 있습니다 .

:파일 이름에 a가 나타날 수 있으므로 -Zgrep 옵션을 사용하여 파일 이름 뒤에 nul 문자(\0)를 출력할 수 있습니다.

grep -rZn $pattern $path | sed -e "s/[[:cntrl:]]\([0-9][0-9]*\).*/:\1/" 

이전과 동일한 예제를 사용하면

src/main/package/A.java:3
src/main/package/A.java:5
src/main/package/A.java:6

답변2

첫 번째 부분에서는 xargs파일 이름에 공백 문자가 없는 경우에만 작동한다는 점에 유의하세요. \'"바라보다리눅스 디렉토리의 전체 내용에서 단어를 검색하는 방법설명과 대안을 찾아보세요.

또한 변수 대체는 항상 큰따옴표로 묶으십시오 "$path". 큰따옴표가 없으면 쉘은 값의 공백과 와일드카드를 확장하므로 $path파일 이름에 공백이나 와일드카드가 포함되어 있으면 따옴표 없이 사용하면 중단됩니다. 마찬가지입니다 $pattern. (웃음을 위해 따옴표를 생략하고 및 h*라는 파일이 포함된 디렉터리에서 검색해 보세요.)hihello

귀하의 버전에 디렉토리를 재귀적으로 탐색하는 옵션이 grep있는 경우 이는 필요하지 않습니다. 이 옵션은 Linux, FreeBSD, Mac OS X, Cygwin 등에서 사용할 수 있습니다. 그렇지 않으면:-rfind-r

find "$path" -type f -exec grep -Hn "$pattern" {} + | awk -F: '{print $1 ":" $2}'

awk또한 파일 이름과 줄 번호만 인쇄하도록 위의 호출을 수정했습니다 . 또한 파일이 하나만 있는 경우에도 항상 파일 이름을 인쇄하도록 -H옵션을 에 전달했습니다 . grep이 코드는 파일 이름에 개행 문자가 포함되어 있지 않다고 가정합니다 :. 가능하다면 상황이 복잡해지며 둘 중 하나를 선택하는 것이 좋습니다.GNU grep에 의존하는 -Z옵션또는 파일을 개별적으로 처리합니다.

find "$path" -type f -exec sh -c 'for x; do grep -n "$0" <"$x" | awk -v fn="$x" -F: 'print fn ":" $1'; done' "$pattern" {} +

답변3

나는 그것을 제거 grep하고 다음을 사용할 것입니다 awk.

find $path -type f -print0 | xargs -0 awk "/$pattern/{print FILENAME,FNR}"

grep그러나 및 사용 cut:

find $path -type f -print0 | xargs -0 grep -nH "$pattern" | cut -d: -f1,2

-type f일반적이지 않은 파일 형식(심볼릭 링크, 디렉터리, 소켓)을 검색하려고 할 때(grep 또는 awk에서) 오류가 발생하지 않도록 이 절을 포함하세요 . 파이프나 소켓에서 읽어야 할 때 다른 프로그램을 사용하고 있다면 해당 프로그램을 망칠 수 있습니다.

find ... -print0 | xargs -0파일 이름에 공백이 있는 문제가 해결되었습니다. 모든 UNIX 시스템에서 사용할 수는 없지만 대부분의 시스템에서 사용할 수 있습니다.

답변4

또한 확인 -c하고 -n유용한 옵션을 확인하십시오.

관련 정보