두 가지 명령을 모두 시도했는데 이 명령은 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
방법 과 유사하게 찾은 각 이름의 전체 경로를 일치시키는 것입니다 .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
답변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
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입니다.
답변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이 더 많은 작업을 수행하므로 시간이 더 오래 걸립니다.