두 명령을 모두 시도했는데 find | grep "filename"
명령이 단순한 명령.
이 동작에 대한 적절한 설명은 무엇입니까?
댓글
답변
(여기서는 GNU find
를 가정합니다.)
사용하기
find filename
은 filename
또는 filename
“디렉터리 인 경우”, 해당 이름이 현재 디렉터리에없는 경우 오류가 발생합니다. ls filename
와 유사한 매우 빠른 작업입니다 (그러나 filename
가 디렉토리 인 경우 재귀 적).
In 대조적으로,
find | grep filename
find
에서 모든 이름 목록을 생성 할 수 있습니다. grep
가 필터링 할 현재 디렉토리 이하입니다. 이것은 분명히 훨씬 느린 작업입니다.
실제로는 의 의도는 다음과 같습니다.
find . -type f -name "filename"
이것은 모든 위치에서 일반 파일의 이름으로 filename
를 찾습니다. 현재 디렉토리 또는 그 이하.
find | grep filename
만큼 빠르지 만 grep
솔루션은 -path "*filename*"
가 iv id = “778e7df849″에서 수행하는 것과 유사하게 발견 된 각 이름의 전체 경로에 대해 filename
를 찾습니다. >
.
혼란은 가 작동합니다.
이 유틸리티는 여러 경로 를 가져와이 경로 아래에있는 모든 이름을 반환합니다.
그런 다음 제한 파일 이름, 경로, 타임 스탬프, 파일 크기, 파일 유형 등에 작용할 수있는 다양한 테스트를 사용하여 반환 된 이름을 제한합니다.
언제
find a b c
find
에 세 경로 a
에서 사용 가능한 모든 이름을 나열하도록 요청합니다. b
및 c
. 이것이 현재 디렉토리에있는 일반 파일의 이름 인 경우 반환됩니다. 그중 하나가 디렉토리의 이름 인 경우 해당 디렉토리 내의 모든 추가 이름과 함께 반환됩니다.
내가 할 때
find . -type f -name "filename"
현재 디렉토리 (.
) 이하의 모든 이름 목록을 생성합니다. 그런 다음 -type f
를 사용하여 이름을 일반 파일, 즉 디렉토리가 아닌 이름으로 제한합니다. 그런 다음 -name "filename"
를 사용하여 filename
와 일치하는 이름에 대한 추가 제한이 있습니다. 문자열 filename
는 *.txt
와 같은 파일 이름 globbing 패턴 일 수 있습니다 (따옴표 만 기억하십시오!).
예 :
다음은 내 홈 디렉토리에서 .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
댓글
-
find filename
는filename
가 디렉터리 유형이 아니거나 디렉터리 유형 인 경우filename
만 반환합니다. 항목 자체가 없음)
답변
비 기술적 설명 : 군중 속에서 Jack 찾기 군중 속에있는 모든 사람을 찾고 Jack을 제외한 모든 것을 고려 대상에서 제거하는 것보다 빠릅니다.
댓글
- 문제는 OP가 Jack이 군중 속에서 유일한 사람이 되십시오. 그렇다면 ‘ 운이 좋은 것입니다.
find jack
는jack
가 ‘ 또는 디렉토리에있는 모든 이름 (‘ 디렉토리 인 경우). ‘find
작동 방식에 대한 오해입니다.
답변
아직 문제를 이해하지 못했지만 더 많은 정보를 제공 할 수 있습니다.
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
. 쓸 것이 전혀 없어도 손실됩니다. grep
에 대한 20 만 개의 파일 (1,300 만 개의 파이프 데이터) :
time find /usr -name lwevhewoivhol
find
는 grep
만큼 빠를 수 있지만
name
에 대한 find
“의 어리 석음은 다른 테스트로 확장되지 않습니다. 대신 정규식을 사용하면 문제가 사라집니다.
:> 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 물론이 테스트를 여러 번 수행했습니다. 캐싱 문제는 첫 번째 답변 이전의 질문에 대한 의견에서도 언급되었습니다. 내
find
버전은 find (GNU findutils) 4.6.0입니다. -
-name '*.txt'
를 추가하는 속도가 느려지는 것이 왜 놀라운가요?find
? 각 파일 이름을 테스트하면서 추가 작업을해야합니다. - @Barmar 한편으로는이 추가 작업을 매우 빠르게 수행 할 수 있습니다. 반면에이 추가 작업은 다른 작업을 절약합니다.
find
는 더 적은 데이터를 작성해야합니다. 그리고 파이프에 쓰는 것은 훨씬 느린 작업입니다. - 디스크에 쓰는 것은 매우 느립니다. 파이프에 쓰는 것은 그렇게 나쁘지 않고 커널 버퍼에 복사 만합니다. 첫 번째 테스트에서
/dev/null
에 더 많이 작성하면 시스템 시간이 덜 사용되었습니다.
답변
알림 : find . -name filename
(그렇지 않으면 “다른 것을 찾고 있습니다. find filename
는 실제로 filename 이라는 경로를 조사합니다. 파일이 거의 없을 수 있으므로 매우 빠르게 종료됩니다.)
5 천 개의 파일을 보유한 디렉토리가 있다고 가정 해보십시오. 대부분의 파일 시스템에서 이러한 파일은 실제로 트리 구조 에 저장되어 특정 파일을 빠르게 찾을 수 있습니다.
따라서 find
에 이름 확인 만 필요한 파일을 찾도록 요청하면 find
에서 질문 해당 파일 및 해당 파일에 대해서만 대용량 저장소에서 매우 적은 페이지를 읽는 기본 파일 시스템으로 전송됩니다. 따라서 파일 시스템이 그만한 가치가있는 경우이 작업은 전체 트리를 가로 지르는 모든 항목을 검색하는 것보다 훨씬 빠르게 실행됩니다.
당신이 평범한 find
를 요구할 때 정확히 당신이하는 일이라면, 당신은 전체 트리를 가로 지르며 읽는다. Every. Single. Entry. 이것은 문제가 될 수 있습니다 (디스크에 많은 파일을 저장해야하는 여러 소프트웨어가 “디렉토리 트리”를 2 ~ 3 개의 구성 요소 깊이로 만드는 이유입니다. 이렇게하면 모든 단일 리프에 더 적은 파일 만 저장하면됩니다) .
Answer
/ john / paul / george / ringo / beatles 파일이 있고 검색중인 파일이 있다고 가정합니다. “stones”라고합니다.
find / stones
find는 “beatles”를 “stones”와 비교하여 “s”와 “b”가 일치하지 않을 때 드롭합니다. .
find / | grep stones
이 경우 find는 “/ john / paul / george / ringo / beatles”를 grep 및 grep wil에 전달합니다. 일치 여부를 결정하기 전에 전체 경로를 통해 작업해야합니다.
따라서 grep은 훨씬 더 많은 작업을 수행하므로 시간이 더 오래 걸립니다.
댓글
- 해보 셨나요?
- 문자열 비교 비용 (매우 간단하고 저렴함)은 IO (또는 캐시 된 경우 시스템 호출) 비용에 의해 완전히 왜소합니다. .
- grep은 ‘ 문자열 비교가 아닙니다. 정규 표현식 비교는 다음 중 하나를 찾을 때까지 전체 문자열을 통해 작업해야 함을 의미합니다. 일치하거나 끝에 도달합니다. 디렉토리 조회는 무슨 일이 있어도 동일합니다.
- @Paranoid 흠, 어떤 버전의 find 에 대해 이야기하고 있습니까? ‘ 데비안에서 사용하던 찾기 ‘와는 다른 것 같습니다.
time find "$HOME" -name '.profile'
는time find "$HOME" | grep -F '.profile'
보다 더 긴 시간을보고합니다. (17s vs. 12s).grep
변형은find
결과의 어느 위치에서나 일치하지만find -name
는 정확히 일치합니다 (이 경우).find filename
빠릅니다 . 나는 이것이 오타이고 OP가find -name filename
를 의미한다고 생각했습니다.find filename
를 사용하면filename
만 검사됩니다 (다른 항목은 없음).