“find | grep 'filename' '을'find 'filename' '보다 훨씬 느리게?


10

두 명령을 모두 시도했는데 명령 find | grep 'filename' 이 간단한 find 'filename' 명령 보다 여러 배 느립니다 .

이 행동에 대한 적절한 설명은 무엇입니까?


2
find와 함께 모든 파일을 나열한 다음 grep에 데이터를 전달하여 처리합니다. find 자체에 사용하면 나열된 모든 파일을 grep에 전달하여 출력을 구문 분석하는 단계가 누락됩니다. 따라서 이것은 더 빠를 것입니다.
Raman Sailopal

어떤 의미에서 느리게? 명령을 완료하는 데 다른 시간이 걸립니까?
Kusalananda

1
이것을 로컬로 재생할 수 없습니다. , time find "$HOME" -name '.profile'보다 긴 시간이보고 time find "$HOME" | grep -F '.profile'됩니다. (17 대 12).
Kusalananda

2
@JenniferAnderson 나는 둘 다 반복적으로 달렸다. 17 초와 12 초는 평균입니다. 그렇습니다. grep유사 콘텐츠는 find결과의 어느 곳에서나 일치하지만 일치하는 find -name항목은 정확히 일치합니다 (이 경우).
Kusalananda

2
예, find filename 빠릅니다 . 나는 이것이 오타이고 OP가 의미한다고 가정했다 find -name filename. 으로 find filenamefilename검사됩니다 (그리고 다른 것은 없습니다).
Kusalananda

답변:


11

( find여기서 GNU를 가정 합니다)

그냥 사용

find filename

것입니다 그냥 반환하기 때문에, 빨리 filename, 또는 내부의 이름 filename그 이름이 현재 디렉토리에 존재하지 않는 경우는 디렉토리 또는 오류의 경우. 디렉토리 와 비슷 ls filename하지만 재귀적인 매우 빠른 작업 filename입니다.

대조적으로

find | grep filename

허용 할 find목록을 생성하는 모든 아래의 현재 디렉토리에서 이름, grep다음 필터링 것입니다. 이것은 분명히 훨씬 느린 작동입니다.

나는 실제로 의도 된 것이

find . -type f -name 'filename'

filename현재 디렉토리 나 그 아래에있는 일반 파일의 이름을 찾습니다 .

이것은 빨리 (또는 비교적 빠른)로 될 것입니다 find | grep filename,하지만 grep해결책은 일치합니다 filename유사 무엇을, 발견 된 각 이름의 전체 경로에 -path '*filename*'함께 할 것입니다 find.


혼란은 어떻게 find작동 하는지에 대한 오해에서 비롯됩니다 .

이 유틸리티는 여러 경로 를 사용하여이 경로 아래의 모든 이름을 반환합니다.

그런 다음 파일 이름, 경로, 타임 스탬프, 파일 크기, 파일 형식 등에 영향을 줄 수있는 다양한 테스트를 사용하여 반환 된 이름 을 제한 할 수 있습니다 .

네가 얘기 할 때

find a b c

당신은 질문 find세 가지 경로에서 사용할 수있는 모든 이름을 나열 a, b그리고 c. 이것이 현재 디렉토리에있는 일반 파일의 이름 인 경우, 해당 파일이 리턴됩니다. 이들 중 하나가 디렉토리 이름 인 경우 해당 디렉토리 내의 모든 추가 이름과 함께 리턴됩니다.

내가 할 때

find . -type f -name 'filename'

현재 디렉토리 ( .)와 그 아래 에있는 모든 이름 목록이 생성 됩니다. 그런 다음을 사용하여 이름을 일반 파일 (예 : 디렉토리 등)의 이름으로 제한합니다 -type f. 그런 다음를 filename사용하여 일치 하는 이름에는 추가 제한이 있습니다 -name 'filename'. 문자열 filename은 파일 이름 글 로빙 패턴 일 수 있습니다 *.txt( 예 : 그냥 인용하십시오!).

예:

다음은 .profile내 홈 디렉토리에서 호출 된 파일을 "찾는"것 같습니다 .

$ pwd
/home/kk
$ find .profile
.profile

그러나 실제로는 경로의 모든 이름 만 반환합니다 (이름 .profile은 하나 뿐이며이 파일의 이름 만 있음).

그런 다음 cd한 단계 위로 올라간 후 다시 시도하십시오.

$ cd ..
$ pwd
/home
$ find .profile
find: .profile: No such file or directory

find명령은 이제라는 경로를 찾을 수 없습니다 .profile.

그러나 현재 디렉토리를보고 반환 된 이름만으로 제한하면.profile 거기에서도 찾을 수 있습니다.

$ pwd
/home
$ find . -name '.profile'
./kk/.profile

1
find filename디렉토리 유형이 아니 거나 디렉토리 유형 이었지만 항목 자체 가없는 filename경우 에만 반환filename
Stéphane Chazelas

2

비 기술적 설명 : 군중에서 잭을 찾는 것이 군중에서 모든 사람을 찾는 것보다 빠르며 잭을 제외한 모든 것을 고려하지 않아도됩니다.


문제는 OP가 잭이 군중에서 유일한 사람이 될 것으로 기대한다는 것입니다. 그렇다면 운이 좋다. find jackjack파일 인 jack경우 디렉토리이거나 디렉토리 인 경우 디렉토리의 모든 이름을 나열 합니다 . find작동 방식에 대한 오해입니다 .
Kusalananda

1

아직 문제를 이해하지 못했지만 더 많은 통찰력을 제공 할 수 있습니다.

Kusalananda와 마찬가지로 find | grep내 시스템 에서 전화가 더 빠르므로 이해가되지 않습니다. 처음에는 일종의 버퍼링 문제를 가정했습니다. 콘솔에 쓰면 다음 파일 이름을 읽는 다음 시스템 호출 시간이 느려집니다. 파이프 쓰기는 매우 빠릅니다. 32 바이트 쓰기에서도 약 40MiB / s (느린 시스템에서는 1MiB의 블록 크기는 300MiB / s)입니다. 따라서 find파이프 (또는 파일)에 쓸 때 파일 시스템에서 더 빨리 읽을 수 있다고 가정 하여 파일 경로를 읽고 콘솔에 쓰는 두 작업이 병렬로 실행될 수 있다고 가정했습니다 ( find단일 스레드 프로세스는 자체적으로 수행 할 수 없음).

그것은이다 find의 오류

두 통화 비교

:> time find "$HOME"/ -name '*.txt' >/dev/null

real    0m0.965s
user    0m0.532s
sys     0m0.423s

:> time find "$HOME"/ >/dev/null

real    0m0.653s
user    0m0.242s
sys     0m0.405s

find(즉 무엇이든간에) 믿을 수 없을만큼 멍청한 짓을한다. 그것은 단지 실행에 무능한 것으로 판명되었습니다 -name '*.txt'.

입력 / 출력 비율에 따라 달라질 수 있습니다

작성 find -name해야 할 내용이 거의 없으면 이길 것이라고 생각할 수도 있습니다 . 하지만 더 부끄러워하지 않습니다 find. 다음에 대해 200K 파일 (13M의 파이프 데이터)에 대해 전혀 쓸 내용이 없어도 손실됩니다 grep.

time find /usr -name lwevhewoivhol

find빨리으로 될 수 grep있지만,

그것은 밝혀 find와의 어리 석음이 name다른 시험으로 확장되지 않습니다. 대신 정규식을 사용하면 문제가 사라집니다.

:> time find "$HOME"/ -regex '\.txt$' >/dev/null     

real    0m0.679s
user    0m0.264s
sys     0m0.410s

나는 이것이 버그로 간주 될 수 있다고 생각합니다. 버그 신고를하려는 사람이 있습니까? 내 버전은 find (GNU findutils) 4.6.0입니다.


당신의 타이밍은 얼마나 반복적입니까? 당신이 한 경우 -name첫 번째 테스트를, 그것은 때문에하지가 캐시되는 디렉토리 내용에 느린되었을 수 있습니다. (테스트 할 때 -name-regex나는 그들이 캐시 효과가 고려 된 후 적어도 거의 같은 시간을 찾을 수 물론 단지의 다른 버전 될 수있다. find...)
psmears

@psmears 물론이 테스트는 여러 번 수행했습니다. 캐싱 문제는 첫 번째 답변 이전의 질문에 대한 의견에서도 언급되었습니다. 내 find버전은 find (GNU findutils) 4.6.0
Hauke ​​Laging

추가 -name '*.txt'가 느려지 는 것이 왜 놀라운가 find? 각 파일 이름을 테스트하여 추가 작업을 수행해야합니다.
Barmar

@Barmar 한 손으로이 추가 작업을 매우 빠르게 수행 할 수 있습니다. 반면에이 추가 작업은 다른 작업을 저장합니다. find적은 데이터를 작성해야합니다. 그리고 파이프에 쓰는 것은 훨씬 느리게 작동합니다.
Hauke ​​Laging

디스크에 쓰는 것은 매우 느리고 파이프에 쓰는 것은 그리 나쁘지 않으며 단지 커널 버퍼에 복사합니다. 첫 번째 테스트에서 더 많은 것을 쓰는 것은 시스템 시간을 /dev/null 사용 했습니다.
Barmar

0

주의 : 나는 당신이 의미한다고 가정 할 것입니다 find . -name filename(그렇지 않으면, 당신은 다른 것을 찾고 있습니다; find filename실제로 filename 이라는 경로를 찾습니다 . 실제로 파일이 거의 없을 수 있으므로 실제로 빨리 종료됩니다).


5 천 개의 파일을 보유한 디렉토리가 있다고 가정하십시오. 대부분의 파일 시스템에서 이러한 파일은 실제로 트리 구조로 저장되므로 지정된 파일을 빠르게 찾을 수 있습니다.

당신이 물어 그래서 find그 이름 만 확인이 필요한 파일을 찾으려면 find것입니다 요청 에 대한 대용량 저장 매우 몇 페이지를 읽 기본 파일 시스템으로, 파일 및 해당 파일 만. 따라서 파일 시스템의 가치가 충분하면이 작업은 전체 트리통과하여 모든 항목을 검색 하는 것보다 훨씬 빠르게 실행됩니다 .

그러나 당신이 평범한 것을 요구할 때 find그것은 정확히 당신이하는 일입니다. 마다. 단일. 기입. 큰 디렉토리의 경우 이것은 문제가 될 수 있습니다 (디스크에 많은 파일을 저장해야하는 여러 소프트웨어가 두 개 또는 세 개의 구성 요소 깊이에 "디렉토리 트리"를 작성하는 이유입니다. 이런 방식으로 모든 단일 리프는 더 적은 수만 보유하면됩니다. 파일).


-2

/ john / paul / george / ringo / beatles 파일이 존재하고 검색중인 파일을 'stones'라고 가정합니다.

find / stones

find는 'beatles'와 'stones'를 비교하여 's'와 'b'가 일치하지 않으면 삭제합니다.

find / | grep stones

이 경우 find는 '/ john / paul / george / ringo / beatles'를 grep에 전달하고 grep이 일치하는지 확인하기 전에 전체 경로를 통과해야합니다.

grep은 더 많은 작업을 수행하므로 더 오래 걸립니다


1
시도해 보셨습니까?
Hauke ​​Laging

3
문자열 비교 비용 (매우 간단하고 저렴함)은 디렉토리 조회의 IO (또는 캐시 된 경우 syscall) 비용으로 완전히 뒤떨어집니다.
Mat

grep은 문자열 비교가 아닙니다. 정규 표현식 비교는 일치하는 것을 찾거나 끝에 도달 할 때까지 전체 문자열을 통과해야합니다. 디렉토리 조회는 무엇이든 동일합니다.
편집증

@Paranoid Hm, 무슨 버전의 find 에 대해 이야기하고 있습니까? 그것은 분명히 이런 건 아니다 발견 내가 데비안에서 사용 해요.
파이프
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.