find . -atime +7 -o -size +`expr 10 \* 1024 \* 2` -print다시 요점만 말하면 이 명령은 현재 디렉토리와 그 서브디렉토리에서 .으로 표현되는 7일 이상 접근되지 않은 (-atime +7)이나 (-o) 파일을 찾는 것으로 이들은 특정 크기보다 (-size +) 더 큽니다. 필자는 expr 명령을 사용해서 필요한 크기를 계산했습니다. 10MB를 목표로 두고 있었고 find는 512 바이트 단위로 생각하므로 10ⅹ1024ⅹ2를 계산해야 했습니다(2ⅹ512 는 1024 이므로).
cd ~/tmp/tst find . -print | wc -l 269find 명령이 실행될 때 발견된 각각의 파일을 서로 다른 라인에 print했다는 것에 주목합시다. 그리고 난 후 그 결과를 파이프해서 행의 수를 세는 (-l) 스위치를 이용해 word count(wc) 명령으로 전달했습니다. 이것은 tst 디렉토리에 269 개의 파일(디렉토리 포함, 유닉스에서 디렉토리는 실제로 파일이기 때문)이 있음을 알려줍니다.
find . -name "*.old" -print | wc -l 67이제 이 *.old 파일들을 삭제하기 위해 무엇을 해야 할까요? 한가지 방법은 -exec 스위치를 이용해서 그것이 rm 명령을 다음과 같이 호출하도록 하는 것입니다.
find . -name "*.old" -exec rm {} \;이 작업이 끝나면 이 명령을 반복해서 *.old 파일들이 남아있는지 확인할 수 있습니다.
find . -name "*.old" -print | wc -l 0이 명령이 잘 동작하기는 하지만 여러 개의 파일들을 지우는 최선의 방법은 아닙니다. 여러분이 -exec 스위치를 사용할 때 마다 find가 발견하는 모든 파일에 대해 개별적인 프로세스가 생성됩니다. 만약 가정용 컴퓨터에서 소량의 파일에 대해 find를 할 때는 문제가 되지 않겠지만 제작 시스템에서 수백 개나 수천 개의 파일에 대해 find를 한다면 문제가 될 것입니다. 어쨌든 이 방법은 다른 방법보다 보다 많은 자원을 소모하기 때문에 느립니다.
find . -name "*.old" -print | xargs rm여기서 필자가 find 명령 끝에 \;를 포함하지 않아도 되었다는 것을 발견할 것입니다. 참고로 그 문자열은 exec에 넘겨지는 명령을 종료하기 위해 사용됩니다. 이 명령에서 xargs를 사용하여 필자는 여전히 확장자가 .old로 끝나는 모든 파일을 지울 것입니다. 발견되는 각각의 파일을 생성하는 것이 아니라 xargs를 통해 오직 한 개의 프로세스만 시작될 것입니다. find가 각각의 파일을 발견함에 따라, 각각의 행에 각 파일의 이름이 오는 목록을 생성할 것입니다. 이 목록은 xargs로 넘겨져서 파일 목록의 모든 행을 받아들여 각 파일을 스페이스로 구분하면서 한 줄로 만들 것입니다. 그리고 나서 xargs는 이 파일 목록 인자를 rm 명령에 넘겨줍니다.
find . -name "*.old" -delete이 명령은 가장 사용하기 쉬운 문법이며 실제로도 파일을 지우는데 가장 효율적인 방법입니다. -delete 스위치는 개별적인 프로세스를 생성할 필요도 없습니다. 모든 파일들은 find 프로세스에 의해 삭제되기 때문입니다. 게다가 이 명령은 언제나 잘 작동할 것입니다. 반면에 xargs 명령은 find가 인자 목록(argument list)으로 명령에 전달될 수 있는 것보다 많은 파일을 발견할 경우 실패할 것입니다. 만약 여러분이 복잡한 디렉토리 구조를 검색하고 있거나 파일명이 아주 길다면 이 제한에 도달할지도 모릅니다. 실제 제한 값이 궁금하다면 설정된 sysctl 값을 확인하면 됩니다.
sysctl -a | grep kern.argmax kern.argmax: 6553665536은 인자 목록에서 최대 바이트(글자) 수를 나타냅니다.
find . -name "*.old" -print이것은 모든 해당 파일의 목록을 보여줄 것입니다. 목록이 적당하다면 -delete 스위치를 사용해 위에서 언급한 예제에서처럼 파일들을 지우면 됩니다.
find . -name "*.old" -ok rm {} \;-ok는 뒤에 나오는 명령을 실행하기 전에 확인을 위해 물어볼 것입니다. rm 명령을 사용해야 한다는 점에 주목하세요. -delete 스위치는 사용할 수 없기 때문입니다. 그리고 -exec를 사용하는 것처럼 {} \; 문법을 사용해야만 -ok가 제대로 동작할 것입니다.
cd find . -type d -ls | head 976142 8 drwxr-xr-x 39 genisis wheel 4096 Mar 3 17:52 . 1413099 2 drwxr-xr-x 2 genisis wheel 512 Mar 3 13:38 ./pdfs 373539 2 drwxr-xr-x 2 genisis wheel 512 Feb 6 12:38 ./tst 1087249 2 drwxr-xr-x 2 genisis wheel 512 Oct 4 07:29 ./perlscripts 650764 2 drwx------ 2 genisis wheel 512 Mar 3 17:52 ./mail 706616 2 drwx------ 4 genisis wheel 512 Sep 22 14:29 ./.kde 706635 2 drwx------ 11 genisis wheel 512 Nov 7 12:36 ./.kde/share 706636 4 drwx------ 3 genisis wheel 1536 Mar 2 18:38 ./.kde/share/config 785986 2 drwx------ 2 genisis wheel 512 Sep 22 14:36 ./.kde/share/config/colors 706682 2 drwx------ 3 genisis wheel 512 Mar 2 18:36 ./.kde/share/fonts-ls 스위치를 이용해 조금 더 보기좋게 꾸며봅시다. 기사 앞부분에서 우리는 출력을 wc -l로 파이프(pipe)하여 얼마나 많은 파일들이 특정 표현을 포함하는지 알아보았습니다.
find . -type d -print | wc -l 256실제로 255 개의 서브디렉토리가 있는 것으로 출력되는데 256중에 한 개는 현재 디렉토리이기 때문입니다. 이제 이 명령을 이용해서 이 디렉토리 스트럭처가 펼쳐져 있는지 잘 알아봅시다.
find . -type d -ls | awk "{print $4 - 2, $NF}" | sort -rn | head 37 . 26 ./.kde/share/apps/kio_http/cache 18 ./.kde/share/apps 15 ./.gimp-1.2 9 ./tmp/tst 9 ./.kde/share 8 ./tmp/tst/h 8 ./tmp/tst/g 8 ./tmp/tst/f 8 ./tmp/tst/e정말 훌륭하지 않습니까? 홈디렉토리(.)에는 37개의 서브 디렉토리가, .kde/share/apps/kio_http/cache 서브디렉토리에는 26 개의 서브디렉토리와 그 외에 다른 서브디렉토리들이 있는 것으로 나타났습니다. 이제 이 find 명령이 어떻게 동작했는지를 알아봅시다. 필자는 -ls 스위치를 이용하여 시작했는데, 이 스위치는 발견되는 각각의 디렉토리에 대해 적절한 정보를 줍니다. 이 정보는 awk 유틸리티로 파이프 되었으며 이는 특정 필드에서 자료를 추출해내기 위해 사용되는 유틸리티입니다. 원래의 -ls 출력에서 결과들이 inode 번호, 블록의 개수, 퍼미션, 링크의 수 등등의 특정한 필드로 출력되었던 것을 기억할 것입니다. awk에게 4번째 컬럼(링크의 개수를 포함하고 있으며 awk에는 $4)에서 정보를 가져다가 그 값에서 2를 빼도록 했습니다(디렉토리 . 이나 .. 에는 관심이 없기 때문에). 게다가 각 디렉토리의 이름도 알고 싶었습니다. 이것이 맨 마지막 칼럼이기 때문에 그 필드를 나타내기 위해 $NF를 사용했습니다. 이러한 명령들을 괄호 {} 안에 나타냄으로써 awk가 find 명령으로부터 받는 모든 파일에 대해 이 작업을 하도록 했습니다. 그리고 난 후 awk에서의 결과를 -rn을 사용하여 sort 명령으로 파이프 했습니다. sort가 수의 출력을 가장 큰 것에서부터 작은 것으로 정렬하여 나는 어떤 디렉토리가 가장 많은 서브디렉토리를 갖고 있는지 볼 수 있었습니다. 나는 이 결과를 모두 출력해서 여러분을 지루하게 하고 싶지 않았기 때문에 최종 결과를 head 명령으로 파이프하여 첫 번째 10가지만을 출력했습니다.
find . -perm 777 -print위의 명령은 정확하게 777 퍼미션을 가진 파일만을 검색합니다. 만약 모든 퍼미션 비트가 아니라 특정 비트에만 관심이 있다면, 다음과 같이 할 수 있습니다
find . -perm -4000 -print이 예제는 SUID 비트가 설정된 파일들만을 출력할 것입니다. (이전 기사에서 퍼미션에 대해 더 많이 읽어보세요.) 또다른 편리한 find 명령은 이것입니다.
find . -perm -0002 -print이것은 다른 사람들이 쓸 수(writable) 있는 모든 파일을 찾을 것입니다. -0002, -002, -02, -2를 사용해도 앞에 있는 0이 있는 것으로 가정되어 같은 결과를 얻는다는 것에 주목하세요.
find . -depth -print | cpio -dump /backup이 명령은 -depth 스위치 없이도 잘 동작하겠지만 항상 그런 것은 아닙니다. 기본값으로 find는 find 명령에서 언급된 지점(내 경우엔 . 이나 나의 홈 디렉토리)에서부터 시작해서 발견된 파일들의 목록을 출력합니다. 즉, 그것이 첫 번째 디렉토리를 출력하고 난 후에야 그 디렉토리의 내용을 출력한다는 것입니다. 만약 find가 읽기 전용의 퍼미션을 가진 디렉토리와 마주친다면 find는 여전히 그 디렉토리의 내용의 목록을 cpio 명령으로 전달하겠지만 cpio 명령은 그 서브디렉토리에 있는 파일을 복제할 권한이 없기 때문이다. cpio가 여전히 디렉토리를 생성할 수 있겠지만 디렉토리를 생성함에따라 cpio는 퍼미션을 읽기 전용으로 설정하고, 그 디렉토리 아래에는 어떠한 파일도 생성할 수 없을 것입니다.
find . -type d -name tmp -prune -o -print | cpio -dump /backup문법이 다소 어색하게 보일 겁니다. -name 스위치를 사용해서 tmp라는 이름의 모든 디렉토리를(-type d)를 찾아서 그 목록을 -prune에 넘겨주었습니다. 그리고 난 후 논리적 or인 -o를 사용해서 그 외의 모든 것이 프린트되게 하고 cpio로 파이프 되었습니다.
이전 글 : 에릭하게만 시리즈 3 - 변환 행렬
다음 글 : 파이썬 암호학: 교실에서 동아리로
최신 콘텐츠