답변:
두 가지 잠재적 인 문제 :
grep -R
( grep
OS / X 10.8 이상 에서 수정 된 GNU 제외 )는 심볼릭 링크를 따르므로 파일에 100GB의 파일 만 있어도 심볼릭 링크 ~/Documents
가 여전히있을 수 있으며 /
파일을 포함한 전체 파일 시스템을 스캔하게됩니다. 처럼 /dev/zero
. 사용하여 grep -r
새로운 GNU와 함께 grep
, 또는 표준 구문을 사용합니다 :
find ~/Documents -type f -exec grep Milledgeville /dev/null {} +
(종료 상태는 패턴이 일치하는지 여부를 반영하지 않습니다).
grep
패턴과 일치하는 선을 찾습니다. 이를 위해 한 번에 한 줄씩 메모리에로드해야합니다. grep
다른 많은 grep
구현 과 달리 GNU 는 읽은 행의 크기에 제한이 없으며 이진 파일에서 검색을 지원합니다. 따라서 사용 가능한 메모리보다 큰 파일 인 매우 큰 행 (즉, 두 줄 바꿈 문자가 매우 큼)이있는 파일이 있으면 실패합니다.
일반적으로 스파 스 파일에서 발생합니다. 다음과 같이 재현 할 수 있습니다.
truncate -s200G some-file
grep foo some-file
그 중 하나는 해결하기가 어렵습니다. 다음과 같이 할 수 있습니다 (여전히 GNU 사용 grep
).
find ~/Documents -type f -exec sh -c 'for i do
tr -s "\0" "\n" < "$i" | grep --label="$i" -He "$0"
done' Milledgeville {} +
입력을에 공급하기 전에 NUL 문자 시퀀스를 하나의 개행 문자로 변환합니다 grep
. 문제는 스파 스 파일로 인한 문제에 적용됩니다.
큰 파일에 대해서만 수행하여 최적화 할 수 있습니다.
find ~/Documents -type f \( -size -100M -exec \
grep -He Milledgeville {} + -o -exec sh -c 'for i do
tr -s "\0" "\n" < "$i" | grep --label="$i" -He "$0"
done' Milledgeville {} + \)
파일이 희소 하지 않고grep
이전 버전의 GNU가있는 경우이 옵션을 2.6
사용할 수 있습니다 --mmap
. 행이 복사되는 대신 행이 메모리에 줄어 듭니다. 즉, 페이지를 파일로 페이징하여 시스템이 항상 메모리를 회수 할 수 있습니다. 이 옵션은 GNU grep
2.6 에서 제거되었습니다
grep
지금까지 처리 한 버퍼를 버릴 수 있습니다. 몇 킬로바이트 이상의 메모리를 사용하지 않고 무기한으로 grep
출력 할 수 있습니다 yes
. 문제 는 선의 크기입니다.
--null-data
옵션도 여기서 유용 할 수 있습니다. 입력 줄 종결 자로 줄 바꿈 대신 NUL을 사용합니다.
나는 보통
find ~/Documents | xargs grep -ne 'expression'
나는 많은 방법을 시도했지만 이것이 가장 빠르다는 것을 알았습니다. 공백이있는 파일은 파일 이름을 잘 처리하지 못합니다. 이 경우에 해당하고 GNU 버전의 grep이있는 경우 다음을 사용할 수 있습니다.
find ~/Documents -print0 | xargs -0 grep -ne 'expression'
그렇지 않은 경우 다음을 사용할 수 있습니다.
find ~/Documents -exec grep -ne 'expression' "{}" \;
exec
모든 파일에 대해 grep 할 것 입니다.
find -print0 | xargs -0 grep -ne 'expression'
find -print0
하고 xargs -0
있으며 지금까지 세 가지 BSD, MINIX 3, Solaris 11,…
이 문제를 해결할 수있는 몇 가지 방법을 생각할 수 있습니다.
한 번에 한 파일 씩 모두 파기하지 말고 한 파일 씩 수행하십시오. 예:
find /Documents -type f -exec grep -H Milledgeville "{}" \;
단어가 들어있는 파일 만 알아야하는 경우 grep -l
대신 수행하십시오. grep은 첫 번째 히트 후 검색을 중단하므로 큰 파일을 계속 읽을 필요가 없습니다.
실제 텍스트를 원한다면 두 개의 별도 greps을 묶을 수 있습니다.
for file in $( grep -Rl Milledgeville /Documents ); do grep -H Milledgeville "$file"; done
grep
파일 이름에 유효한 구분 기호를 사용하여 출력 하므로이를 수행하지 않아야 함 ). 당신은 또한 인용해야합니다 $file
.
for
파일을 두 개의 인수로 처리하게됩니다)
6TB 디스크를 잃어버린 데이터를 검색하고 메모리가 소진되었습니다. 오류가 발생했습니다. 다른 파일에서도 작동합니다.
우리가 생각해 낸 해결책은 dd를 사용하고 청크를 그렙하여 디스크를 청크로 읽은 것입니다. 이것은 코드 (big-grep.sh)입니다.
#problem: grep gives "memory exhausted" error on 6TB disks
#solution: read it on parts
if [ -z $2 ] || ! [ -e $1 ]; then echo "$0 file string|less -S # greps in chunks"; exit; fi
FILE="$1"
MATCH="$2"
SIZE=`ls -l $1|cut -d\ -f5`
CHUNKSIZE=$(( 1024 * 1024 * 1 ))
CHUNKS=100 # greps in (100 + 1) x 1MB = 101MB chunks
COUNT=$(( $SIZE / $CHUNKSIZE * CHUNKS ))
for I in `seq 0 $COUNT`; do
dd bs=$CHUNKSIZE skip=$(($I*$CHUNKS)) count=$(( $CHUNKS+1)) if=$FILE status=none|grep -UF -a --context 6 "$MATCH"
done