몇 천 개의 파일을 가져 오기


13

cca 26 000 파일이있는 디렉토리가 있으며이 모든 파일을 grep해야합니다. 문제는 가능한 한 빨리 필요하다는 것이므로 grep이 find 명령에서 하나의 파일 이름을 가져 와서 일치하는 파일을 스크립트로 만드는 것이 이상적이지 않습니다. "인수 목록이 너무 깁니다"문제가 발생하기 전에이 모든 파일을 정리하는 데 2 ​​분이 걸렸습니다. 어떻게 생각하십니까? 편집 : 항상 새로운 파일을 만드는 스크립트가 있으므로 모든 파일을 다른 디렉토리에 넣을 수는 없습니다.


1
사용 findxargsgrep -R
Eddy_Em

잘 작동하지만 10 분이 걸립니다 ...
user2778979

답변:


19

find:

cd /the/dir
find . -type f -exec grep pattern {} +

( 일반 파일 -type f만 검색 합니다 ( 일반 파일을 가리키는 경우에도 심볼릭 링크 제외). 디렉토리를 제외한 모든 유형의 파일에서 검색하려는 경우 (하지만 fifos 또는 / dev / zero와 같은 일부 파일 유형은 당신은 일반적으로 (읽기를 원하지 않습니다), GNU- -type f특정으로 대체하십시오 ! -xtype d( symlink 확인 후 디렉토리-xtype d 유형의 파일과 일치합니다 )).

GNU로 grep:

grep -r pattern /the/dir

(하지만 최신 버전의 GNU grep이 없으면 디렉토리로 내려갈 때 심볼릭 링크를 따라야합니다). -D read옵션 을 추가하지 않으면 비정규 파일은 검색되지 않습니다 . 최신 버전의 GNU grep는 여전히 심볼릭 링크를 검색하지 않습니다.

아주 오래된 GNU 버전은 find표준 {} +구문을 지원하지 않았지만 비표준을 사용할 수 있습니다.

cd /the/dir &&
  find . -type f -print0 | xargs -r0 grep pattern

성능은 I / O 바운드 일 가능성이 높습니다. 검색을 수행하는 시간은 스토리지에서 모든 데이터를 읽는 데 필요한 시간입니다.

데이터가 중복 디스크 어레이에있는 경우 한 번에 여러 파일을 읽으면 성능이 향상 될 수 있습니다 (그렇지 않으면 성능이 저하 될 수 있음). 성능이 I / O 바운드가 아니고 (예를 들어 모든 데이터가 캐시에 있기 때문에) 여러 CPU가있는 경우 동시도 greps도움이 될 수 있습니다. GNU xargs-P옵션으로 그렇게 할 수 있습니다 .

예를 들어, 데이터가 3 개의 드라이브가있는 RAID1 어레이에 있거나 데이터가 캐시에 있고 여유 시간이 3 개의 CPU가있는 경우 :

cd /the/dir &&
  find . -type f -print0 | xargs -n1000 -r0P3 grep pattern

(여기서는 한 번에 최대 3 개의 파일을 동시에 실행하여 1000 개의 파일마다 -n1000새로운 grep파일 을 생성합니다 .)

그러나 출력 grep이 리디렉션되면 3 개의 grep프로세스 에서 잘못 인터리브 된 출력이 생겨서 다음과 같이 실행할 수 있습니다.

find . -type f -print0 | stdbuf -oL xargs -n1000 -r0P3 grep pattern

(최신 GNU 또는 FreeBSD 시스템에서) 또는 --line-bufferedGNU 옵션을 사용하십시오 grep.

경우 pattern고정 된 문자열 인의 추가 -F옵션은 문제를 개선 할 수있다.

멀티 바이트 문자 데이터가 아니거나 해당 패턴이 일치하는 경우 데이터가 멀티 바이트 문자인지 여부는 중요하지 않습니다.

cd /the/dir &&
  LC_ALL=C grep -r pattern .

성능을 크게 향상시킬 수 있습니다.

이러한 검색을 자주 수행하는 경우 많은 검색 엔진 중 하나를 사용하여 데이터를 색인화 할 수 있습니다.


3

단일 디렉토리의 26000 파일은 대부분의 파일 시스템에 적합합니다. 이 큰 디렉토리를 읽는 데 상당한 시간이 소요될 수 있습니다. 각각 수백 개의 파일 만있는 더 작은 디렉토리로 분할하는 것을 고려하십시오.

전화 find를 잘못하지 않으면 전화 를 걸면 성능이 저하 될 수 있습니다. 디렉토리를 순회하고 너무 긴 명령 행을 실행하려고 시도 할 위험이 없도록하는 빠른 방법입니다. -exec grep PATTERN {} +파일 당 한 번만 -exec grep PATTERN {} \;실행되는 명령 호출 당 가능한 한 많은 파일을 압축 하는을 사용해야 grep합니다. 파일 당 한 번 실행되는 파일은 한 번만 실행됩니다.


고마워, 나는 그것에 대해 구글 뭔가를하고 아마 나눌 것입니다. 나는 당신이 쓰고있는 것을 정확하게 만들었고 grep보다 3 배 더 오래 걸렸습니다.
user2778979

Gilles, 한 디렉토리에있는 26,000 개의 파일과 100 개의 디렉토리에 분산 된 26,000 개의 파일의 성능이 크게 다를 것이라고 말씀하십니까?
user001

1
@ user001 예. 그것들의 차이는 파일 시스템과 기본 스토리지에 따라 다르지만 단일 디렉토리의 26000 파일과 비교하여 100 개의 디렉토리 각각에서 260 개의 파일로 파일 시스템이 훨씬 빠를 것으로 예상합니다.
Gilles 'SO- 악마 그만'

설명해 주셔서 감사합니다. 불일치의 기초를 이해하기 위해이 시점에서 후속 질문 을했습니다.
user001

0

모든 파일을 여러 번 grep 해야하는 경우 (스크립트 실행) 램 디스크를 살펴보고 모든 파일을 복사 한 다음 여러 번 grep하는 것이 좋습니다. 이는 검색 속도를 향상시킵니다. 100 배 이상

당신은 충분한 램이 필요합니다. 그렇지 않으면 파일을 색인화해야합니다 (예 : lucene 또는 nosql 데이터베이스에 넣고 쿼리를 실행합니다.


다른 곳에서 언급했듯이, 이는 실행할 파일이 너무 많다는 사실에는 도움이되지 않습니다 grep. "항상 새 파일을 작성하는 스크립트가 있기 때문에 모든 파일을 다른 디렉토리에 넣을 수는 없습니다."
Jeff Schaller

-2

디렉토리의 모든 파일

grep 'search string' *

재귀 적으로

grep -R 'search string' *

-1을 정교하게 관리 하시겠습니까?
Markus

4
나는 공감하지는 않았지만 몇 가지 문제가 있습니다. OP는 "arg list too long"을 언급했습니다. 첫 번째 항목은 수정되지 않으며 아마도 OP가 이전에하고 있었던 것입니다. 두 번째는 그 점에서 도움이되지 않습니다 ( .대신에 사용 했었을 것입니다 *). *재귀 디렉토리의 파일이 아닌 -R을 사용하지만 도트 파일은 제외합니다. -r과 반대로 -R은 최신 버전의 GNU grep에서도 심볼릭 링크를 따릅니다. 또한 현재 디렉토리의 파일 이름에 문제가 있습니다.-
Stéphane Chazelas
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.