작은숲:위키노트/Find
리눅스에서 find 명령어는 주어진 이름이나 조건에 맞는 파일을 찾고 지정한 명령을 실행한다. find의 기본 구문은 아래와 같다.
find [path...] [expression]
path는 현재 작업 디렉토리(.) 혹은 특정 디렉토리를 지정할 수 있다. 하나 이상의 디렉토리를 지정하는 것도 가능하다. expression에는 옵션과 검색 조건, 실행 명령을 지정할 수 있다. find는 이 글에 나온 옵션과 검색 조건, 실행 명령 외에도 더 많은 것들을 지원하니 자세한 내용은 맨페이지를 참고하도록 하자. 이 글은 find 맨페이지에 나온 내용 중 일부분을 옮긴 것이다.
옵션
-help--help- 사용법을 출력한다.
-version--version- 버전을 출력한다.
-depth-d- 디렉토리에 대해 명령을 실행하기 전에 디렉토리 내에 있는 파일들에 대해 먼저 명령을 실행한다.
-delete명령을 줄 때는 자동으로 이 옵션이 주어진다. -maxdepth levels- 검색과 명령을 실행할 최대 디렉토리 깊이를 지정한다. levels은 양의 정수만 가능하다. 지정한 디렉토리만을 대상으로 할 때 levels는 1이 된다.
-warn-nowarn- 경고 메시지를 출력하거나 출력하지 않는다.
검색 조건
찾을 대상의 이름 지정
-name name- 찾을 대상의 이름을 지정한다. 이때 찾을 이름은 대소문자를 구분한다. '*', '?', '[]' 등의 메타문자를 쓸 수 있다.
-name sample– 'sample'이라는 이름을 가진 대상-name "sam*"– 'sam'으로 시작하는 이름을 가진 대상-name "*.txt"– '.txt'로 끝나는 이름을 가진 대상 (확장자가 txt인 대상)[1]-name \*.txt– '.txt'로 끝나는 이름을 가진 대상 ('*'은 셸에 의해 해석되는 메타문자이기 때문에 셸에서 해석되지 않도록 역슬래시('\')를 붙인다)
-iname name- 대소문자의 구분 없이 찾을 대상의 이름을 지정한다.
-regex pattern-iregex pattern- 대상의 이름을 찾을 때 정규 표현식을 사용한다. 앞에 'i'가 붙으면 대소문자를 구분하지 않는다.
찾을 대상의 형식 지정
-type type- 찾을 파일의 형식을 지정한다.
-type f– 일반 파일-type d– 디렉토리-type l– 심볼릭 링크-type b– 블럭(block)-type c– 캐릭터(character)-type p– 파이프(named pipe, FIFO)-type s– 소켓(socket)
찾을 대상의 타임스탬프 지정
먼저 앞에 붙은 접두어에 따라 어떤 시각을 대상으로 할 것인지 결정된다.
- m – 대상이 마지막으로 수정된(modified) 시각
- a – 대상이 마지막으로 읽기 혹은 접근된(accessed) 시각
- c – 대상의 상태가 마지막으로 변경된(changed) 시각
그리고 시간의 단위가 뒤에 따라온다.
- min – 분
- time – 일 (24시간)
이후에는 시간이 나온다. 시간은 숫자이어야 하며, 음수와 양수가 올 수 있다. 음수인 경우에는 '이전', 양수인 경우에는 '이후'를 뜻한다.
-mmin 10- 지금으로부터 10분 전의 이후에 수정된 대상
-atime 10- 지금으로부터 10일 전의 이후에 읽힌 적이 있는 대상
-cmin -20- 지금으로부터 10분 전의 이전에 상태가 변경된 대상
비교 대상을 다른 파일로 지정할 수도 있다.
-cnewer file- file이 수정된 시각 이후에 상태가 변경된 대상
-newer file- file이 수정된 시각 이후에 수정된 대상
찾을 대상의 퍼미션 지정
-perm mode로 찾고자 하는 대상의 퍼미션을 지정할 수 있다. mode에는 숫자 형식의 모드(0775)나 문자 형식의 모드(u=xwr)가 올 수 있다. 그리고 mode의 앞에는 '-', '/', '+', 세 가지의 추가 설정이 붙거나 붙지 않을 수 있다.
- mode – 정확하게 지정한 모드와 일치하는 대상. 예를 들어,
-perm g=w라고 했다면 다른 퍼미션 설정 없이 오직 그룹 쓰기 퍼미션(0020)만 있어야 한다. - -mode – 지정한 모드와 모두 일치하는 대상. 예를 들어,
-perm g=w라고 했다면 다른 퍼미션은 상관 없이 그룹 쓰기 퍼미션(0664, 0666, 0020 등)이 설정된 경우에 일치한다. - /mode, +mode – 지정한 모드 중 어느 하나라도 일치하는 대상. 두 설정은 비슷한 동작을 한다. 하지만 '+'는 추후 삭제될 옵션이므로 '/'을 쓰도록 한다.
찾을 대상의 소유 사용자나 그룹 지정
-gid n- n GID를 갖는 대상
-group gname- gname 그룹의 소유인 대상
-nogroup- 설정된 GID가 존재하지 않은 경우
-nouser- 설정된 UID가 존재하지 않은 경우
-uid n- n UID를 갖는 대상
-user uname- uname 사용자의 소유인 대상
찾을 대상의 크기 지정
-size n[cwbkMG]- 찾을 대상의 크기를 지정한다. 숫자 뒤에 오는 접미사는 단위를 뜻한다.
- 'b' – 512 바이트 블럭(512-byte blocks, 접미사가 붙지 않았을 때 사용되는 기본 단위)
- 'c' – 바이트(bytes)
- 'w' – 워드(2-byte words)
- 'k' – 킬로바이트(Kilobytes, units of 1024 bytes)
- 'M' – 메가바이트(Megabytes, units of 1048576 bytes)
- 'G' – 기가바이트(Gigabytes, units of 1073741824 bytes)
기타 검색 조건
-readable- 읽을 수 있는 대상
-writable- 쓸 수 있는 대상
-executable- 실행할 수 있는 대상
-empty- 비어있는 대상
-fstype type- type 파일시스템에 있는 대상으로 제한 (type에는 nfs, ufs, tmp, mfs 등이 올 수 있다)
연산자
find에서 하나 이상의 조건들을 연산자를 통해 연산할 수 있다. 이것은 보통의 프로그래밍 언어에서 사용하는 연산자와 비슷하다.
( expr )- 조건식을 괄호로 묶는다. 수학에서와 마찬가지로 괄호로 묶인 연산식이 먼저 연산된다.
! expr-not expr- 부정 연산자. expr 조건식이 참이면 결과값은 거짓이다.
!연산자의 경우 셸에서 다른 의미로 해석되는 메타문자이기 때문에\!와 같이 역슬래시를 붙여 셸에서 해석되지 않도록 해야 한다. expr1 expr2expr1 -a expr2expr1 -and expr2- 논리곱(AND) 연산자. expr1과 expr2가 모두 참이어야 참이다. expr1이 거짓이면 expr2는 검사하지 않는다.
expr1 -o expr2expr1 -or expr2- 논리합(OR) 연산자. expr1과 expr2, 둘 중 하나만 참이면 참이다.
expr1 , expr2- 순차(쉼표) 연산자. 조건식에서는 expr1은 연산은 하지만 값은 무시되고, 연산식의 결과값은 expr2가 된다. expr1과 expr2 둘 모두 실행할 때 유용하다.
실행 명령
-print- 검색한 대상의 완전한 경로를 한 줄에 하나씩 화면에 출력한다. 즉 대상의 경로 뒤에 개행문자('\n')를 붙여서 출력한다.
-print0- 검색한 대상의 완전한 경로를 화면에 출력한다. 대상의 경로 뒤에는 개행문자('\n') 대신 널문자('\0') 붙여서 출력한다.
-printf format- 검색한 대상의 완전한 경로를 format 형식에 맞게 화면에 출력한다. format은 C 언어 등에서 사용하는 형식 지정자와 같다.
-fprint file- 검색한 대상을 화면에 출력하는 대신 file에 저장한다. file은 없는 경우 새로 만들고, 있는 경우에는 덮어 쓴다.
-fprint /dev/stdout은-print와 같은 명령이다. -fprint0 file- 검색한 대상의 완전한 경로를 file에 저장한다. 대상의 경로 뒤에는 개행문자('\n') 대신 널문자('\0') 붙인다.
-fprintf file format- 검색한 대상을 format 형식에 맞게 file에 저장한다. format은 C 언어 등에서 사용하는 형식 지정자와 같다.
-ls- 검색한 대상을 ls -dils 명령의 출력 형식처럼 출력한다.
-fls file- 검색한 대상을 ls 명령의 출력 형식으로 file에 저장한다.
-delete- 검색한 대상을 삭제한다.
-depth옵션을 주지 않아도 자동으로-depth옵션에 따라 동작한다. -exec command ;-exec command {} ;- 검색한 대상에 대해 command 명령을 실행한다. command의 끝은 세미콜론(;)으로 구분 짓는다. 명령창에서 실행할 때는 셸에서는 세미콜론(;)이 특별한 의미를 갖기 때문에 앞에 역슬래시(\)를 붙여서 사용한다. '{}'을 쓰면 command가 인자가 필요한 경우 찾은 대상을 인자로 넘겨준다.
-exec rm -rf {} \;. -exec command {} +-exec command {} ;명령은 대상을 하나씩 command의 인자로 넘겨 실행하지만,-exec command {} +명령은 대상들을 모두 합쳐 마지막에 command의 인자로 넘긴다. 즉 command의 인자는 개별 대상이 아니라 모든 대상의 목록이 된다.-execdic command ;-execdir command {} ;-exec과는 달리-execdic에서는 하위 디렉토리에 있는 대상부터 명령을 실행한다.-execdir command {} +-exec command {} +과 마찬가지로 하위 디렉토리에 있는 대상부터 인자로 넘겨줄 대상의 목록에 포함시켜 마지막에 모든 대상의 목록을 command의 인자로 넘겨준다.-ok command ;-exec와 비슷하지만 command를 실행하기 전에 사용자에게 물어본다.-okdir command ;-execdir과 비슷하지만 command를 실행하기 전에 사용자에게 물어본다.
예제
find /tmp -name core -type f -print | xargs /bin/rm -f/tmp디렉토리 아래에서 'core'라는 이름을 가진 파일을 찾아 삭제한다.-print명령으로 출력한 값들이 xargs 명령어로 넘어가서/bin/rm의 인자가 된다. 이 경우 만약 파일 이름에 개행문자나 따옴표, 공백문자가 있으면 오류가 생긴다.find /tmp -name core -type f -print0 | xargs -0 /bin/rm -f/tmp디렉토리 아래에서 'core'라는 이름을 가진 파일을 찾아 삭제한다. 여기서는-print0명령으로 출력한 값들은 널문자로 구분되어 있다. 이것을 xargs 명령어에서-0옵션으로 받아 이를 구분해서/bin/rm의 인자로 넘겨준다. 이 경우에는 파일 이름에 개행문자나 공백문자, 따옴표가 들어가도 오류가 생기지 않는다.find . -type f -exec file '{}' \;- 현재 작업 디렉토리 아래에 있는 모든 파일들을 찾아 그 파일들을 대상으로 file 명령을 실행한다.
'{}'와\;는 셸에서 원치 않게 해석되는 것을 방지하기 위해 따옴표와 역슬래시를 붙여준 것이다. find / \( -perm -4000 -fprintf /root/suid.txt '%#m %u %p\n' \) , \( -size +100M -fprintf /root/big.txt '%-10s %p\n' \)- 여기에서는 두 find 명령을 한번에 실행하게 하고 있다. 이 명령을 실행하면 find는 루트 디렉토리에서부터 setuid가 설정된 파일을 찾아
/root/suid.txt에 저장하고, 크기가 100Mbytes 이상인 파일을 찾아/root/big.txt파일에 저장한다. 이 명령에서는 두 가지 find 명령을 실행하지만 전체 파일시스템은 한 번만 탐색하게 된다. find $HOME -mtime 0- 홈 디렉토리 아래에서 지난 24시간 이내에 수정된 파일과 디렉토리 등을 출력한다.
-mtime은 조건에 맞는 파일을 찾기 위해 현재 시각에서 파일이 수정된 시각을 뺀 후 24시간으로 나눈다. 그런 후 소수점 이하는 버리기 때문에 24시간이 지나지 않은 값들은 모두 0이 된다. 따라서-mtime의 인자로 0을 주면 지난 24시간 이내에 수정된 파일을 찾게 된다. find /sbin /usr/sbin -executable \! -readable -print/sbin과/usr/sbin디렉토리에서 실행 가능하지만 읽을 수 없는 파일을 찾아 출력한다. 부정 연산자 !는 셸에서 해석되는 메타문자이므로 역슬래시를 붙였다.find . -perm 664- 현재 작업 디렉토리 아래에서 퍼미션이 정확히 644인 파일만 찾는다.
find . -perm -664- 현재 작업 디렉토리 아래에서 퍼미션이 664를 포함하는, 즉 소유 사용자와 그룹은 읽기(퍼미션 4)와 쓰기(퍼미션 2)를 할 수 있고 그 외의 사용자는 읽기를 할 수 있는 퍼미션을 갖는 파일을 찾는다. 이 경우 퍼미션이 664, 666, 764, 775, 777 등인 파일이 포함된다.
find . -perm /222- 현재 작업 디렉토리 아래에서 퍼미션이 소유 사용자가 쓸 수 있거나, 소유 그룹이 쓸 수 있거나, 다른 사용자가 쓸 수 있는 파일을 찾는다. 즉 사용자나 그룹, 다른 사용자가 누구든 쓸 수 있는 파일이 포함된다. 200, 020, 002, 600, 640, 644, 700, 755 등의 퍼미션을 갖고 있는 파일이 해당된다.
find . -perm /220find . -perm /u+w,g+wfind . -perm /u=w,g=w- 위 세 명령은 같다. 현재 작업 디렉토리 아래에서 소유 사용자가 쓸 수 있거나 소유 그룹이 쓸 수 있는 파일을 찾는다.
find . -perm -220find . -perm -g+w,u+w- 위 두 명령은 같다. 현재 작업 디렉토리 아래에서 소유 사용자와 소유 그룹이 모두 쓸 수 있는 파일을 찾는다.
find . -perm -444 -perm /222 ! -perm /111find . -perm -a+r -perm /a+w ! -perm /a+x- 위 두 명령은 같다. 현재 작업 디렉토리 아래에서 모든 사용자가 읽을 수 있고(
-perm -444), 어떤 사용자가 쓸 수 있고(-perm /222), 어떤 사용자도 실행할 수 없는(! -perm /111) 파일을 찾는다. find /home -empty -print/home디렉토리 아래에서 비어있는 파일을 찾아 출력한다.find . -name "*.php" -ls- 현재 작업 디렉토리 아래에서 '.php'로 끝나는 파일(확장자가 php인 파일)을 찾아 ls 명령어의 출력 형식으로 출력한다.
find / -name "test*" -type d -print- 루트 디렉토리 아래에서 'test'로 시작하는 디렉토리만 찾아 출력한다.
find /home /var/www /var/log -empty -print/home,/var/www,/var/www디렉토리 아래에서 비어있는 파일을 찾아 출력한다.find . -mtime -10 -exec rm -rf {} \;- 현재 작업 디렉토리 아래에서 10일 이전에 수정한 파일(디렉토리 포함)을 찾아 모두 삭제한다.
find . -name "*.php" -exec grep "curl" {} \; -print- 현재 작업 디렉토리 아래에서 '.php'로 끝나는 파일(확장자가 php인 파일)을 찾아 내용에 'curl'이 있으면 출력한다.
find . -name "*.php" -exec perl -pi -e "s/hello/hi/g" {} \; -print- 현재 작업 디렉토리 아래에서 '.php'로 끝나는 파일(확장자가 php인 파일)을 찾아 내용에 'hello'가 있으면 모두 'hi'로 수정하고 출력한다.
find /var/www/sample -name "*.php" -exec grep -n "function connect_server" {} \;find /var/www/sample -name "*.php" | xargs grep -n "function connect_server"/var/www/sample디렉토리 아래에서 '.php'로 끝나는 파일(확장자가 php인 파일) 중에서 'function connect_server' 문자열(connect_server()함수 정의)이 있는 파일을 찾아 그 문자열의 줄 번호와 함께 출력한다.find /home -perm 700 -type d -exec chmod 750 {} \;chmod 750 `find /home -perm 700 -type d`/home디렉토리 아래에서 퍼미션이 700인 디렉토리를 찾아 750으로 수정한다.find /home -maxdepth 2 -name ".bash_history" -exec grep -H "rm" {} \;- 사용자 중에 최근 rm 명령어를 사용한 적이 있는지 확인한다.
tar zcvf last-mod.tar.gz $( find . -type f -mmin -60 )- 현재 작업 디렉토리 아래에서 1시간 이전에 수정된 파일들만 찾아
last-mod.tar.gz파일로 압축한다.
참고
- https://www.gnu.org/software/findutils/manual/html_mono/find.html
- http://man7.org/linux/man-pages/man1/find.1.html
주석
| 배포판 | |
|---|---|
| 서버 프로그램 | |
| 시스템 도구 | |
| 시스템 보안 | |
| 시스템 설정 | |
| HOWTO 문서 | |
| 사용자 설정 | |
| 활용 | |
| 명령어 | |