...
파일/디렉토리 검색
find는 리눅스에서 파일 및 디렉토리를 검색할 때 사용하는 명령어다.
$ find [경로] [옵션] [표현식]
$ find [PATH] [OPTION] [EXPRESSION]
find 명령에는 몇 가지 옵션과 많은 수의 표현식(Expression)이 존재하는데, find 명령의 검색 결과가 지정된 표현식의 조합에 따라 결정되기 때문에 표현식은 매우 자주 사용되어 익혀둘 필요성이 있다.
find 옵션
-H 심볼릭 링크를 따라가지 않고, Command Line Argument를 처리할때 예외.
-L 심볼릭 링크에 연결된 파일정보 사용.
-P 심볼릭 링크를 따라가지 않고, 링크 자체 정보를 사용
-Olevel 쿼리 최적화를 활성화한다. level : 0-3
-D [옵션] 디버깅 기능 사용.
help 디버깅 옵션을 설명.
exec -exec, -execdir, -ok, -okdir 관련 진단 정보를 표시.
opt 최적화와 관련된 진단 정보 표시.
rates 각 속성의 성공한 빈도를 나타냅니다.
tree 표현식 트리를 표시.
search 디렉토리 트리를 자세히 탐색.
stat stat(2), lstat(2)에 대한 추적을 호출한다.
find 표현식(expression) 정리
표현식 | 의미 |
-name | 주어진 이름의 파일이나 디렉터리를 찾는다 (가장 많이 쓰이는 옵션) $ find -name '*.txt' 현재 디렉터리 이하의 모든 디렉터리에서 .txt로 끝나는 파일 및 디렉터리를 싹 찾는다. |
-user | 지정한 사용자의 파일이나 디렉터리를 찾는다 (위에가 이름가지고 찾았다면 이거는 사용자 기준) |
-group | 지정한 그룹 소유의 파일이나 디렉터리를 찾는다 |
-uid | 지정한 UID소유의 파일이나 디렉터리를 찾는다 (아이디번호로 찾기) |
-gid | 지정한 UID 소유의 파일이나 디렉터리를 찾는다 (그룹번호로 찾기) |
-perm | 지정한 허가권 값을 갖는 파일이나 디렉터리를 찾는다 (permission의 약자) ex) -perm 755 : 퍼미션 값이 755로 설정된 파일이나 디렉터리 |
-type | 지정한 파일 유형을 찾는다. (파일만 찾고 싶을때 또는 디렉터리만 찾고 싶을 경우가 많다) d: 디렉터리, f: 일반 파일, l: 링크 파일, b: 블록 디바이스, c: 캐릭터 디바이스, p:파이프 디바이스, s:소켓 파일 (주로 -type f 옵션이나 -type d 옵션을 많이 쓴다) |
-atime n | access time 접근 시간 기준으로 찾는다. n : n일 이전에 접근한 파일 찾기 (exactly) +n : n보다 오래된 녀석들 기준 (greater), -n : n일부터 지금까지 즉 n일 내에 접근했던 파일들을 불러준다. (less) |
-ctime n | change time 수정 시간 기준으로 찾는다 |
-mtime n | modify time 변경 시간 기준으로 찾는다 |
-mmin n | mmin은 분이 기준 (mtime은 기준이 day) |
-empty | 빈 파일(파일의 크기가 0일 경우)이나 빈 디렉터리일 경우 출력 |
-exec | find로 파일을 찾고 바로 연계하여 어떠한 명령을 내릴 수 있는 옵션. 결과값은 {} 기호로 표시하고 \;로 끝내야 함. |
-ls | 'ls -l'과 같은 역할 |
-size n | n블록 길이의 파일을 찾는다. +n은 n블록보다 큰 파일을 찾으며 (greater) -n은 n블록보다 작은 파일을 찾는다 (less) 보통 nc라는 형태로 많이 사용되는데 n은 문자 길이의 파일을 의미하고, c는 character를 의미하여 1문자는 1바이트이므로 보통 바이트 단위로 인식해서 사용한다. |
-inum n | node번호가 n인 파일 찾기 |
-iname | 대소문자 구별 안하고 이름으로만 찾을 때 (insensitive의 약자) |
-maxdepth n | 검색 시 주어진 정수값 n만큼의 서브 디렉터리만 검색. (현재 내 폴더에서부터 n 깊이까지만) |
-mindepth n | maxdepth의 반대. |
-prune | 찾은 결과 중 디렉터리가 해당될 때 그 디렉터리 이름만 출력 (하위 디렉터리에 해당되는게 있어도 들어가서 찾지 않는다) |
-newer | 옵션 뒤에 적힌 파일보다 최근에 변경된 파일을 찾는다 ex) find -newer 'abc.c' abc파일보다 최근에 변경된 파일을 찾음 |
-cnewer | 앞의 newer가 내용 변경이라면 cnewer라면 파일 상태 |
2>/dev/null | 맨 뒤에 이 옵션을 붙이면 퍼미션 접근 불가한것은 화면에 출력하지 않는다. |
검색결과를 파일의 절대경로로 표시. 디폴트 옵션이다. | |
-print0 | -print옵션과 같은데 검색결과를 한줄로 이어서 표시. |
표현식 연산자 종류
표현식 사용 시 연산자(Operator)를 사용하여 "두 개 이상의 표현식" 조합이 가능하다
표현식 조합 | 설명 |
(expression) | expression 우선순위 지정. |
!expression -not expression |
expression 결과에 NOT 연산. |
expression -a expression expression -and expression expression expression |
expression 간 AND 연산. |
expression -o expression expression -or expression |
expression 간 OR 연산. |
find 명령에서 두 개 이상의 표현식을 사용할 때 연산자를 지정하지 않으면, 기본적으로 -a (AND)가 적용된다.
# 둘이 같다.
$ find -empty -print
$ find -empty -a -print
find 실전 예제
파일명으로 찾기 (-name)
$ find # 현재 디렉토리의 파일 및 디렉토리 출력
$ find -print0 # 현재 디렉토리의 모든 내용을 줄 바꿈 없이 출력.
$ find . -empty # 현재 경로 하위에서 빈 디렉터리 혹은 크기가 0인 파일 검색
$ find [PATH] # PATH에 있는 파일 및 디렉토리 리스트 표시.
$ find . -name [FILENAME] # 현재 디렉토리 아래 모든 파일 및 디렉토리 검색.
$ find ~ -name [FILENAME] # 사용자의 홈디렉터리 하위에서 파일이름 검색
$ find . -name "STR*" # 지정된 문자열로 시작하는 파일 검색.
$ find . -name "*STR*" # 지정된 문자열이 포함된 파일 검색.
$ find . -name "*STR" # 지정된 문자열로 끝나는 파일 검색.
$ find . -name "B*" # B로 시작하는 파일 검색. 결과 : ./B_FILE
$ find /user -name '*.txt' # /user 디렉토리에서 .txt 파일이름으로 끝나는 파일이름 검색
$ find . -name "*.EXT" -delete # 확장자 검색 후 파일 삭제.
타입으로 찾기 (-type)
option | type |
f | regular file |
d | directory |
c | character special |
b | block special |
l | symbolic link |
s | socket |
p | fifo |
# 현재 경로 하위 파일/디렉터리/심볼릭링크에서 [NAME]을 검색
$ find . -name [NAME] -type f,d,l
# -type 종류
# b : block special
# c : character special
# d : directory
# f : regular file
# l : symbolic link
# p : FIFO
# s : socket
$ find . -name build -type f # build라는 이름의 일반 파일 검색.
$ find . -name PROJ -type d # PROJ라는 이름의 디렉토리만 검색
파일 크기로 찾기 (-empty, -size)
옵션 | 단위 |
c | 1byte 단위 |
b | 1block 단위(1block = 512 bytes) |
w | 2 bytes 단위 |
k | 1 kilobytes |
M | 1 metabytes |
G | 1 gigabytes |
# 현재 경로 하위에서 파일 사이즈로 검색
$ find . -size +[SIZE1]c -size -[SIZE2]c
# 파일 크기 값 뒤에 'c' 또는 'k'를 붙임으로써 바이트 단위 또는 킬로바이트의 크기 값을 지정
# b:block, c:bytes, w:2bytes, k:kbytes, M:mbytes, G:gbytes
# +(초과) 또는 -(미만)
$ find . -size 1024c # 파일 크기가 1024 바이트인 파일 검색.
$ find . -size +1024c # 파일 크기가 1024 바이트를 초과하는 파일 검색.
$ find . -size -1024c # 파일 크기가 1024 바이트 미만인 파일 검색.
$ find . -size +1024c -size -2048c # 파일 크기가 1024 바이트 초과, 2048 바이트 미만인 파일 검색
# . 현재 디렉토리에서 타입이 d(디렉토리) 인 파일들 중에 사이즈가 100이상인걸 검색
$ find . -type d -size +100
검색 결과 나열하는 방법 (-print / -print0)
일반적으로 print가 기본 옵션이고 별도로 지정해주지 않으면 -print 가 들어간다.
찾은 내용이 화면으로 출력되며 각 결과는 newline(각 라인이 개행되며 보기좋게)으로 끝난다.
반면 -print0 을 사용하면 각 결과는 null 문자(\0)로 끝난다.
이렇게 하는 이유는 파일이나 디렉토리 이름에 newline이나 공백이 들어가 있는 경우에도 정확하게 처리할 수 있기 때문이다.
그러나 화면에 보기에는 한줄로 처리되어 좋지는 않다.
정리하자면, -print0 을 쓰는 것은 찾은 파일로 다른 일을 할 때 정확하게 처리하기 위함이다.
$ find ./ -name "*.bak" -print
$ find ./ -name "*.bak" -print0
검색된 파일에서 추가 명령 실행하기 (-exec)
- {} : find 에서 찾아낸 검색 결과가 하나씩 들어가는 부분
- \; : -exec 다음부분에 나와있는 명령어를 실행하라는 부분
# 현재 디렉토리에서 c 확장자 파일 상세 정보 출력. (ls 명령 실행)
$ find . -name "*.c" -exec ls -l {} \;
# 확장자가 c 인 파일의 라인 수 출력. (wc 명령 실행)
$ find . -name "*.c" -exec wc -l {} \;
# .c 파일에 문자열 main이 있는지 검색. (grep 명령 실행)
$ find . -name "*.c" -exec grep "main" {} \;
# .java 파일에 문자열 class가 있는 라인 표시.
$ find . -name "*.java" -exec grep -n "class" {} \;
# 검색된 파일을 특정 [경로]로 복사 (cp 명령 실행) > tar.gz 파일을 /mnt/usb/ 에 복사
$ find . -name "*.tar.gz" -exec cp {} /mnt/usb/ \;
# 모든 c 파일 검색 결과를 source-list.txt에 저장 (입출력 재지정 redirection ">" 실행)
$ find . -name "*.c" > source-list.txt
$ find / -name "*.c" 2> /dev/null # 에러 메시지를 표시하지 않음. (입출력 재지정 명령어 포스트 참고할것)
# 검색된 파일로 압축파일 생성 (tar 명령 실행)
$ find . -name [NAME] -exec tar -xcvf [파일명] {} \;
# test 디렉토리에서 권한이 rw-rw-r-- 인 파일을 find해서 (rm 명령 수행)
$ find test -perm 664 -exec rm {} \;
+ 팁 ( 구분자 + 와 \; 의 차이)
-exec 옵션의 제일 끝에 구분자는 + 와 \; 이렇게 두 가지로 나누어져 있는데 성능 면에서 + 가 더 좋다고 알려져 있다.
왜냐하면 \; 를 마지막 구분자로 사용하면 각 파일에 대해 별도의 프로세스를 실행하게 되는데 이로 인해, RAM과 처리 시간 모두에서 심각한 페널티가 발생할 수 있기 때문이다.
구분자 더하기 기호 '+' 를 사용하면 모든 표현식의 결과가 연결되어 전체적으로 한 번만 실행되는 -exec 명령에 전달된다.
find -name '파일명*' -exec tar -cvfz 파일명.tar.gz {} \;
find -name '파일명*' -exec tar -cvfz 파일명.tar.gz {} +
특정 파일 권한을 가진 파일을 검색 (-perm)
$ find . -perm 0664 # 현재 경로에서 특정권한의 파일/디렉터리 검색
# test 디렉토리에서 권한이 rw-rw-r-- 인 파일을 find해서 rm명령 수행
$ find test -perm 664 -exec rm {} \;
정규표현식 패턴으로 파일명 검색 (-regex)
- -regex 옵션을 사용하면 grep처럼 파일이름을 패턴 검색이 가능하다
# 파일 이름이 숫자.txt 인 것들
find . -regex ".*/[0-9]+.txt"
특정 시간 이후/이전 수정된 파일 (-mtime, -atime, -ctime)
- -mtime, -atime, -ctime 등을 사용하면 접근/생성/변경 등의 날짜를 기준으로 파일을 찾을 수 있다.
# 만일 현재시간이 10월 10일 이라고 가정한다면,
$ find -mtime -3 # 3일(72시간)보다 새로움 -> 10.7 ~
$ find -mtime 3 # 4일(96시간) 전에서 3일(72시간)전까지 -> 10.6 ~ 10.7
$ find -mtime +3 # 4일(96시간)전보다 과거 -> ~ 10.6
+ 개념이 난해한 find 타임스탬프 옵션에 대해서 따로 상세히 정리해 보았다.
하위 디렉토리 무시하기 (-prune)
$ find . -name "*문자*" -prune
서브 디렉토리 내용 제한 검색 (-depth)
-
-maxdepth 1 : 최대 디렉토리 한 단계만
-
-mindepth 1 : 명령행 지정된 경로(한 단계)를 제외하고 찾기
$ find . -maxdepth 1 -name [NAME] # 현재 경로에서만 [NAME] 검색 (하위 디렉터리 미포함)
동일 이름 파일 목록 얻기
$ find . -type f -printf "%f\n" | sort | uniq -c | grep -v ' 1 '
하위 디렉토리에 존재하는 파일 갯수
$ find */ | cut -d/ -f1 | uniq -c
# 참고자료
https://recipes4dev.tistory.com/156
https://jhnyang.tistory.com/144
https://www.psjco.com/24
이 글이 좋으셨다면 구독 & 좋아요
여러분의 구독과 좋아요는
저자에게 큰 힘이 됩니다.