"find | grep 'filename'" 명령이 "find 'filename'"보다 훨씬 느린 이유는 무엇입니까?

"find | grep 'filename'" 명령이 "find 'filename'"보다 훨씬 느린 이유는 무엇입니까?

두 가지 명령을 모두 시도했는데 이 명령은 find | grep 'filename' 간단한 명령보다 몇 배나 느립니다 find 'filename' .

이 행동에 대한 올바른 설명은 무엇입니까?

답변1

(나는 find이것이 GNU라고 가정하고 있다)

만 사용

find filename

회의filename디렉터리인 경우 내부 이름만 반환하고 현재 디렉터리에 이름이 없으면 오류만 반환하므로 더 빠릅니다 . filename이는 매우 빠른 작업으로 유사합니다 ls filename(그러나 filename디렉터리인 경우 재귀적임).

대조적으로,

find | grep filename

find목록을 생성 할 수 있습니다 .모두그러면 현재 디렉터리와 다음 디렉터리의 이름이 grep필터링됩니다. 이는 분명히 훨씬 느린 작업입니다.

내가 추측하는 것실제로원래 목적은 이랬는데

find . -type f -name 'filename'

이것은 현재 디렉토리나 다음 디렉토리에서 filename일반 파일의 이름을 찾습니다.

이는 빠르거나 매우 빠르지만 해결 방법은 find | grep filename방법 과 유사하게 찾은 각 이름의 전체 경로를 일치시키는 것입니다 .grepfilename-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

답변2

비기술적 설명: 군중 속에서 Jack을 찾는 것이 Jack을 제외한 모든 사람을 제외하고 군중 속에서 모든 사람을 찾는 것보다 빠릅니다.

답변3

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

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

findgrep하지만 다음과 같이 빠를 수도 있습니다.

find이 어리 석음은 name다른 테스트로 확장되지 않은 것으로 나타났습니다 . 대신 정규식을 사용하면 문제가 사라집니다.

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

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

이건 버그라고 볼 수 있을 것 같아요. 버그 보고서를 제출할 의향이 있는 사람이 있나요? 내 버전은 find(GNU findutils) 4.6.0입니다.

답변4

/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이 더 많은 작업을 수행하므로 시간이 더 오래 걸립니다.

관련 정보