사이트 내 전체검색
[linux] find 유틸리티의 철학
로빈아빠
https://cmd.kr/server/427 URL이 복사되었습니다.

본문

find 유틸리티의 철학

------------------
출처 : KLDP BBS
------------------

find 를 제법 잘 쓰는 사람은 다 아는 얘기일 것 같지만, 흔히들 사용하면서도 그 많은 옵션이 잘 안들어오는 사람들을 위해 정리하고자 글을 써본다.
find의 철학은 그 이름에서 이미 감춰져 있다고 해도 과언이 아니다. find를 통해서 할 수 있는 것이 고작 원하는 이름의 혹은 원하는 속성을 가진 파일을 찾는 것이라 생각한다면 그것은 정말 누구나 사용할 줄 아는 방법으로서의 find 이다.
find의 철학은 다음과 같다. 어디에 이런 글이 쓰여있는지는 나도 모르겠지만, 경험상 정리하자면,
find 는 true/false에 의한 directory 탐색기이다.

신선한가? 그렇다면 계속 읽을 정도로 find라는 처녀 혹은 꽃미남에 대해 호기심을 가질 만한 사람이라 생각하시라.

-----------------------------------------------------------------------------
우선 다들 그러하듯이 man find를 한번 수행해보고 true/false라는 말이 얼마나 나오는지 한 번 살펴보시라. 가능하면, 리눅스의 man find와 솔라리스의 man find를 비교하는 것도 좋을 것이다.

살펴보니 리눅스보다 솔라리스에서 더 많은 true/false라는 말을 발견하게 될터인데, 솔라리스 쪽은 의도 중심적인 표현이고 리눅스쪽은 사용자 중심쪽 표현이기 때문일 것이다.
예 1) find /usr/include -name '*.h'

위 문장은 확장자가 .h 인 파일들을 /usr/include에서 찾는 다는 것을 쉽게 알 수 있다. 하지만, man page를 자세히 읽어보면, 이 문장은 다음과 같이 해석될 수 있다.
만약 현재 스캔하고 있는 파일의 이름이 '*.h'에 일치한다면 참이며, 참인 조건으로 더이상의 비교를 하라는 지시가 없으므로 함축된 -print를 수행한다. 즉, find /usr/include -name '*.h' -print 라고 명시적으로 밝히는 것과 동일하다.
예 2) find /usr/include -name '*.h' -ls

HPUX find에는 -ls 명령이 없지만 솔라리스와 리눅스에는 존재하므로 설명을 드리자면, 위의 문장은 '*.h'에 일치하는 파일에 대하여 ls -l 과 같은 명령을 수행했을 때 처럼 자세한 정보를 출력하게 된다. -ls를 설명하고자하는 것이 아니라, 이 문장을 true/false 이론(?)에 근거하여 다시 설명하자면,
이름이 '*.h'에 일치하게 되면 ls -l 을 수행한 결과를 화면에 나타내라라는 뜻이다.
즉,
find /usr/include -name '*.h' -a -ls

라는 뜻이다. find 의 여러 연산자 중에 -a, -o 는 각각 AND, OR를 의미한다. man page에는

-and is assumed where the operator is omitted. (linux)
Expression [ -a ] Expression - Concatenation of expressions (the AND operation is implied by the juxtaposition of two primaries or may be explicitly stated as -a) (aix; solaris, hpux도 같다)

라는 것을 알 수 있다. (리눅스에만 존재하는 -and는 -a와 같은 뜻이다.)
즉, 쉽게 사용해 왔던,
find -name '*.h' -exec grep 'size_t' {} ;

이런 류의 것들이 실은
find -name '*.h' -a -exec grep 'size_t' {} ;

와 같이 해석된다는 것이다.
-----------------------------------------------------------------------------
지금까지 눈에 씌여 있던 귀차니즘의 막을 걷는 작업을 하였다. -print 와 -a 는 실상 find의 철학을 잊고 쉽게 사용할 수 있는 유틸리티로 만드는 일종의 음모였다라고 생각하시라.
자, 다음과 같은 것은 어떻게 표현해야할까? /usr/include 에 수행한다고 가정하고, <ul> <li>.h가 들어가지 않은 것들에 대한 리스트 <li>grep size_t 로 한 줄도 출력되지 않는 헤더파일들 <li>헤더하나를 a.h 로 복사해 왔는데, 이것과 일치하는 파일 </ul> 첫번째 것은 두 가지 방법으로 가능하다. find /usr/include ! -name '*.h' find /usr/include -name '*.h' -o -print 처음 방법이야 흔히 사용하던 표현식의 반대이므로 바로 이해될 것이고, 두번째는 -o 즉, OR라는 것은 처음것이 거짓인 경우 두번째 것을 해봐야 참값을 알 수 있는 수식으로 C언어나 스크립트 언어들을 익혀 봤다면 흔히 쓰이는 트릭(?)으로 잘 알 수 있을 것이다.
두 번째는 일단, grep 의 exit status가 한 줄이라도 발견하면 정상 값을 돌리고 그렇지 않으면 오류값을 돌린다는 사실을 알아야한다.
$ grep -q size_t /usr/include/stdio.h $ echo $?

size_t 대신 다른 것으로 확인해보면, 발견되면 정상(0), 없는 것이면 오류(1)를 나타냄을 알 수 있다. solaris의 경우 grep 을 /usr/xpg4/bin/grep 을 사용하도록 PATH를 조절하는 것이 -q를 사용할 수 있다. -q는 quiet의 의미를 가진다. 즉, 우리는 exit status만 관심있다는 의미이다.
그러면 두 번째 질문도 다음과 같이 표현 할 수 있다.
find /usr/include -exec grep -q size_t {} ; -o -print

즉, {}에 치환하여 grep 을 수행해본 결과 참이아니라면, 즉 한 줄도 발견되지 않았다면(-o) 출력하라(-print).

세 번째 질문은 cmp를 사용하면 된다. 여기에도 귀엽게스리 -s 옵션이 있다. (많은 유틸리티든지 이런 용도로 사용되는 옵션이 있다. s는 silent !)
find /usr/include -exec cmp -s a.h {} ; -a -print

-----------------------------------------------------------------------------
이 페이지는 find 옵션들을 설명하려는 것이 아니라 철학을 설명하는 것이므로, 더 가렵더래도 긁어주지 않음을 용서하시라.
find 는 뒤에 붙은 장황한 옵션, 명령들에 대해서 참 거짓을 확실히 정할 때까지 계속 수행하는 것을 염두에 둔다면 -a, -o, 그리고 (, )로 사용할 수 있는 여러 조합에 대해 상상의 날개를 펼칠 수 있을 것이다.

다시 말하지만, find 는 true/false를 기반으로하는 디렉토리 탐색기이다.

댓글목록

등록된 댓글이 없습니다.

1,139 (10/23P)

Search

Copyright © Cmd 명령어 52.15.72.229