
150,000개 이상의 파일이 있는 디렉토리가 있습니다. 텍스트 변수에 텍스트가 저장된 모든 파일 목록을 만들고 해당 파일 목록을 다른 변수에 저장하고 싶습니다.
나는 먼저 다음을 시도합니다.
searchtext="Subject: Your"
files = $(grep "$searchtext" ./* | awk '{print ($1)}' )
, 이 방법은 디렉터리에 있는 적당한 수의 파일에 대해 작동하지만 150,000개의 파일이 포함된 디렉터리에서 실행하면 "매개변수 목록이 너무 깁니다."라는 오류가 생성됩니다. (Awk with print는 grep 결과에서 파일 이름만 추출하는 데 사용됩니다.)
files=$(grep "$searchtext" ./* | awk '{print ($1)}') 는 150K 파일 디렉터리에서 작동하지만 실행하는 데 거의 90분이 걸리는 것으로 나타났습니다.
파일에 있는 경우 $searchtext 문자열은 파일 시작 부분에 있습니다. 그래서 grep이 텍스트의 처음 30줄만 표시하도록 제한하면 작업 속도를 크게 높일 수 있다고 생각했습니다. 어떻게 해야할지 모르겠는데 찾아보니디렉토리에 있는 각 파일의 처음 50줄을 어떻게 재귀적으로 grep합니까?거기에서 몇 가지 제안을 시도했습니다. 내 작업에 가장 적합한 것은 다음과 같습니다.
searchtext="Subject: Your"
find . -type f -exec head -n 30 {} + | grep "$searchtext"
이는 허용 가능한 시간 내에 실행되지만 검색 텍스트가 포함된 파일의 파일 이름을 출력하지 않습니다. grep -l을 시도했지만 "find: head' terminated by signal 13 ". Somewhere it was suggested that the using "\" instead of "+" might be more appropriate. However, that also generates an error: "find: missing argument to
-exec' "라는 오류가 발생했습니다.
파일 이름이 포함된 grep 결과를 조사할 때 또 다른 문제가 발생할 것으로 예상했습니다. grep 출력을 변수에 할당하려고 하면 다음과 같습니다.
files = $(find . -type f -exec head -n 30 {} + | grep "$searchtext")
"ut1.sh: 16행: 파일: 명령을 찾을 수 없습니다"라는 오류가 발생합니다. 어떤 이유로 "files" 변수가 명령으로 해석됩니까? 내 스크립트 이름은 ut1.sh입니다. 이전에는 문제 없이 여러 번 이런 방식으로 변수를 할당했습니다.
내 bash 버전은 GNU bash, 버전 4.1.2(2)-release (x86_64-redhat-linux-gnu)입니다.
어떻게 완료되었으며 내 시도에 어떤 문제가 있습니까?
감사해요
답변1
일치하는 파일 이름 목록을 얻으려면 스위치를 사용하여 출력을 처리 하지 않고 파일 이름만 가져올 grep
수 있습니다. 일치하는 파일의 경우 패턴을 한 번 찾아 중지할 수 있으므로 속도도 더 빠릅니다.-l
awk
grep
grep -le "$searchtext" ./*
간단한 할당으로 출력을 변수에 넣을 수 있습니다(그러나 공백과 와일드카드가 있는 파일 이름은 문제를 일으킬 수 있습니다).
files=$(grep -le "$searchtext" ./* )
이것에 관해서는:
find . -type f -exec head -n 30 {} + | grep "$searchtext"
여기의 파이프는 find
및 를 구분 grep
하므로 각 파일의 처음 30줄을 효과적으로 연결한 다음(여기서 파일 이름을 추적할 수 없음) 결과를 grep합니다. grep -l
전체 입력에 일치하는 항목이 있는지 여부만 알려줄 수 있습니다. find
각 파일의 합계를 개별적으로 결합 head
하려면 내부에서 셸을 실행해야 합니다 grep
.
export searchtext
find . -type f -exec sh -c 'head -n 30 "$1" | grep -q "$searchtext" && echo "$1"' sh {} \;
하지만 우리도 awk
그렇게 할 수도 있습니다. 이렇게 하면 처음 30줄(GNU awk)에서만 패턴을 찾을 수 있습니다.
awk -vpattern="$searchtext" 'FNR <= 30 && $0 ~ pattern { print FILENAME; nextfile }' *
또는 찾기를 사용하세요:
find . -type f -exec awk -vpattern="$searchtext" 'FNR <= 4 && $0 ~ pattern { print FILENAME; nextfile }' {} +
답변2
bash
4.4+ 및 GNU의 경우 grep
:
readarray -td '' files < <(grep -rZFle "$searchtext" .)
이메일 파일인 경우 제목을 찾고 있는 것 같으니 여기에서 제목만 검색해 보세요. GNU 사용 awk
:
readarray -td '' files < <(
SEARCH="$searchtext" find . -type f -exec gawk -v ORS='\0' -v RS='\r?\n' '
$0 == "" {nextfile}
index($0, ENVIRON["SEARCH"]) {print FILENAME; nextfile}' {} +
)