find가 때때로 명령 행 경로 인수와 일치하는 이유는 무엇입니까?


9

리눅스에서는

cd /tmp
mkdir foo; cd foo

이제 달리기

find . -name 'foo'

출력을 제공하지 않습니다. 달리는 동안

find /tmp/foo -name 'foo'

/tmp/foo나에게 이해가되지 않는 출력 을 제공합니다 . 누군가 이유를 설명 할 수 있습니까?


2
주어진 경로 안에 명시된대로 경로를 찾으십시오 . 입력하신 내용 ./이 맞지 않습니다foo
Costas

@ 코스타 : 이해합니다. 내가 이해하지 못하는 것은에 대한 절대 경로를 제공하면 왜 차이가 생겼는지 find입니다.
York

@York 어떤 상황에서는 항상 올바른 행동이 없습니다. 검색 경로 외부 bar에있는 파일을 가리키는 이름의 심볼릭 링크를 상상해보십시오 foo. 일치할까요?
Hauke ​​Laging 2016 년

1
.과는 /tmp/foo동일하지 않습니다 - 그들은 같은 디렉토리에 두 개의 서로 다른 하드 링크입니다; find /tmp/foo/. -name 'foo'아무것도 찾지 못했습니다.
jimmij

@jimmij :을 실행할 때 find /tmp/foo -name 'foo'bash가 디렉토리 /tmp/foo에서 foo라는 파일 을 찾도록 요청했습니다 . 디렉토리 /tmp/foo가 비어 있으므로 아무것도 리턴하지 않아야합니다. 왜 반환하는지 이해하지 못합니다 /tmp/foo. 반면에,을 실행할 때 find . -name 'foo'bash에게 똑같은 것을 요청했습니다. 즉, 현재 디렉토리에서 파일을 찾는 /tmp/foo중 이름이 'foo'이고 파일을 찾지 못했습니다.
York

답변:


15

find지정된 디렉토리 트리를 순회하고 찾은 각 파일에 대해 주어진 표현식을 평가합니다. 순회는 주어진 경로에서 시작됩니다. find . -name foo작동 방식에 대한 요약은 다음과 같습니다 .

  • 명령 행의 첫 번째 경로 : .
    • 기본 이름 ( .)이 패턴과 일치 foo합니까? 아니요, 아무 것도하지 마십시오.
      그것은 /tmp/foo같은 디렉토리의 다른 이름입니다. 그러나 find그것을 알지 못합니다 (그리고 그것을 찾으려고해서는 안됩니다).
    • 경로가 디렉토리입니까? 그렇습니다. 의 항목을 열거하고 .각 항목에 대해 순회 프로세스를 수행하십시오.
      • 디렉토리가 비어 있습니다 : 그것은 이외의 항목을 포함하지 .하고 ..있는 find재귀 적으로 통과하지 않습니다. 작업이 끝났습니다.

그리고 find /tmp/foo:

  • 명령 행의 첫 번째 경로 : /tmp/foo
    • 기본 이름 ( foo)이 패턴과 일치 foo합니까? 예, 조건이 일치합니다.
      • 이 조건과 연관된 조치가 없으므로 경로를 인쇄하는 기본 조치를 수행하십시오.
    • 경로가 디렉토리입니까? 그렇습니다. 의 항목을 열거하고 /tmp/foo각 항목에 대해 순회 프로세스를 수행하십시오.
      • 디렉토리가 비어 있습니다 : 그것은 이외의 항목을 포함하지 .하고 ..있는 find재귀 적으로 통과하지 않습니다. 작업이 끝났습니다.

그래서 발생 ./tmp/foo같은 디렉토리입니다,하지만 보장에 충분하지 않습니다 find모두에서 동일한 동작이 있습니다. 이 find명령에는 동일한 파일의 경로를 구별하는 방법이 있습니다. -name술어는 그 중 하나입니다. find /tmp/foo -name foo시작 디렉토리 및 그 아래에있는 파일을 찾습니다 foo. find . -name .시작 디렉토리와 만 일치합니다 ( .재귀 순회 중에는 찾을 수 없음).


"반복적으로 순회하지 않는. 및 .. 이외의 항목은 포함되지 않습니다." 나는 "재귀 적으로 가로 지르지 않는다"는 것을 ".."라고 가정한다. 그것이 맞다면, ".."의 맥락에서 "재귀 적으로 가로로 가로 지른다"는 것은 무엇입니까?
Faheem Mitha

@FaheemMitha는 "하지 트래버스 재귀 않는다"모두 적용 .하고 ... (경우 find횡단 .재귀, 다시하고 다시하고 다시 디렉토리를 통해가는 종료하고 ... 것) .그리고 ..그들은 디렉토리 항목으로 표시, 단지 특별한 표기하지 않습니다.
Gilles 'SO- 악의를 멈춰라'

5

테스트가 적용되기 전에 명령 행 인수의 정규화가 없습니다. 따라서 사용 된 경로에 따라 결과가 다릅니다 (심볼릭 링크가 포함 된 경우).

cd /tmp
mkdir foo
ln -s foo bar
find /tmp/foo -name foo
find /tmp/bar -name foo

"귀하의 사례"에서 두 통화 모두 동일한 결과를 제공하므로 혼동 될 수 있습니다. -mindepth 1시작점을 무시하고 싶을 때 사용할 수 있습니다 (POSIX가 아닐 수도 있음).


-mindepth 1공장. 그러나, 나는 아직 이유를 이해하지 않습니다 find . -name 'foo'find /tmp/foo -name 'foo'다르게 동작합니다.
York

2

(gnu) find는 명령 행 인수와의 비교를 시작하여 디렉토리 구조에서 더 깊이 내려 가기 때문에 명령에 제공된 경로 내에서 발견 된 모든 일치를 표시합니다 (따라서 -maxdepth 0테스트를 기본 레벨 또는 명령 행 인수로 제한합니다) 설명에 -mindepth 1따라 명령 줄 인수를 건너 뜁니다 man find. 이것이 find /tmp/foo -name 'foo'디렉토리 자체가 비어 있어도 하나의 일치 항목을 생성 하는 이유 입니다.

find . -name 'foo'반면에 .(도트)는 동일한 inode에 대한 하드 링크처럼 작동하는 특수 파일 이기 때문에 결과를 /tmp/foo얻지 못합니다. 파일 이름은 별도의 특수 파일 이름과 같으며 심볼릭 링크 나 적용되는 표현식이 아닙니다. 쉘에 의한 경로명 확장. 따라서 주어진 예제에서 find가 명령 줄 인수에 적용한 첫 번째 테스트는에 .정의 된 이름 패턴과 일치하지 않으므로 일치하는 항목이 표시되지 않습니다 -name 'foo'. 패턴에 /tmp/foo/.대한 테스트 -name는 경로의 기본 이름에서만 수행되므로 ( man find여기서는 참조 ), 역시 마찬가지 입니다 ..

이 동작은 사용자 관점에서 예상되지 않거나 직관적으로 보이지 않을 수도 있지만 (처음에는 혼란 스러웠지만) 버그를 구성하는 것이 아니라 (man and info page)에 설명 된 논리 및 기능과 일치합니다. gnu) 찾기.


0

Gilles의 답변에 댓글을 달려고했지만 댓글에 맞추기에는 너무 길었습니다. 이런 이유로 나는 그것을 내 자신의 질문에 대한 답으로 제시하고 있습니다.

Gilles의 설명 (그리고 Shevek도 마찬가지)은 분명하고 합리적입니다. 여기서 중요한 점 find은 주어진 경로 내 파일의 파일 이름을 재귀 적으로 일치시킬뿐만 아니라 주어진 경로 자체의 기본 이름과 일치하려고 시도한다는 것입니다.

반면에 이것이 find버그가 아니라 작동 하는 방식이라는 증거가 있습니까? 내 의견으로는, 그것의 결과가 일치하지 않을 경우 더 나은 것 find .find ABSOLUTE-PATH불일치가 항상 혼란 때문에 "무엇이 잘못된 것인지"에서 개발자에게 내려고 많은 시간을 낭비 할 수있다. 필자의 경우 스크립트를 작성하고 있었고 경로는 변수에서 가져 왔습니다. 내 스크립트가 제대로 작동하려면 내가 생각하는 것은 글을 쓰는 것 find $path/. -name 'pattern'입니다.

마지막으로 계속 진행하기 전에 find항상 .현재 디렉토리를 사용하여 일관된 결과를 얻을 수 있다고 생각 합니다.


-1

foo상대 검색을 시작한 디렉토리에 이름이 지정된 오브젝트가 없습니다 .

절대 이름을 시작 디렉토리로 사용할 때보고 할 때 gfind버그 가 있다고 가정하면 올 바릅니다 /tmp/foo.

Gfind표준과 다양한 편차가 있습니다. 다른 표준을 찾은 것 같습니다. 보다 표준 호환 솔루션이 마음에 드시면이 솔루션의 sfind일부인 것이 좋습니다 schilytools.

-name디렉토리 검색 결과에 적용됩니다. 언급 한 두 경우 중 어느 것도 작업 foo에서 디렉토리 항목 을 반환하지 않습니다 readdir().


나는 이것이 버그라고 생각합니다. 결과는 다음과 같습니다 find --version. find (GNU findutils) 4.4.2 Copyright (C) 2007 Free Software Foundation, Inc. 라이센스 GPLv3 + : GNU GPL 버전 3 이상 < gnu.org/licenses/gpl.html >
York

글쎄, find(POSIX 인증)을 사용하여 예제 명령을 확인 gfind하고 sfind; 문제는 사용할 때만 존재합니다 gfind. Linux에서는 gfind기본 이름이 아닌 name 아래에 설치됩니다 find.
schily

3
find /tmp/foo -name foo출력 하기 에 적합합니다 /tmp/foo. (Cc @York) 이것은 OpenBSD find, GNU find, BusyBox find, Solaris find및 기타 POSIX 호환 동작입니다 find( "검사 할 파일 이름의 기본 이름이 패턴 (…)" 과 일치하면 기본은 true로 평가됩니다. 경로 피연산자로 전달되고 readdir호출은 포함 되지 않습니다 ).
Gilles 'SO- 악마 그만'
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.